mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
history purge
This commit is contained in:
12
nfq/Makefile
Normal file
12
nfq/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=c99 -s -O3
|
||||
LIBS = -lnetfilter_queue -lnfnetlink -lcap -lz
|
||||
SRC_FILES = *.c
|
||||
|
||||
all: nfqws
|
||||
|
||||
nfqws: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f nfqws *.o
|
312
nfq/darkmagic.c
Normal file
312
nfq/darkmagic.c
Normal file
@@ -0,0 +1,312 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "darkmagic.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
uint16_t tcp_checksum(const void *buff, int len, in_addr_t src_addr, in_addr_t dest_addr)
|
||||
{
|
||||
const uint16_t *buf=buff;
|
||||
uint16_t *ip_src=(uint16_t *)&src_addr, *ip_dst=(uint16_t *)&dest_addr;
|
||||
uint32_t sum;
|
||||
int length=len;
|
||||
|
||||
// Calculate the sum
|
||||
sum = 0;
|
||||
while (len > 1)
|
||||
{
|
||||
sum += *buf++;
|
||||
if (sum & 0x80000000)
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
len -= 2;
|
||||
}
|
||||
if ( len & 1 )
|
||||
{
|
||||
// Add the padding if the packet lenght is odd
|
||||
uint16_t v=0;
|
||||
*(uint8_t *)&v = *((uint8_t *)buf);
|
||||
sum += v;
|
||||
}
|
||||
|
||||
// Add the pseudo-header
|
||||
sum += *(ip_src++);
|
||||
sum += *ip_src;
|
||||
sum += *(ip_dst++);
|
||||
sum += *ip_dst;
|
||||
sum += htons(IPPROTO_TCP);
|
||||
sum += htons(length);
|
||||
|
||||
// Add the carries
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
|
||||
// Return the one's complement of sum
|
||||
return (uint16_t)(~sum);
|
||||
}
|
||||
void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr)
|
||||
{
|
||||
tcp->check = 0;
|
||||
tcp->check = tcp_checksum(tcp,len,src_addr,dest_addr);
|
||||
}
|
||||
uint16_t tcp6_checksum(const void *buff, int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
const uint16_t *buf=buff;
|
||||
const uint16_t *ip_src=(uint16_t *)src_addr, *ip_dst=(uint16_t *)dest_addr;
|
||||
uint32_t sum;
|
||||
int length=len;
|
||||
|
||||
// Calculate the sum
|
||||
sum = 0;
|
||||
while (len > 1)
|
||||
{
|
||||
sum += *buf++;
|
||||
if (sum & 0x80000000)
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
len -= 2;
|
||||
}
|
||||
if ( len & 1 )
|
||||
{
|
||||
// Add the padding if the packet lenght is odd
|
||||
uint16_t v=0;
|
||||
*(uint8_t *)&v = *((uint8_t *)buf);
|
||||
sum += v;
|
||||
}
|
||||
|
||||
// Add the pseudo-header
|
||||
sum += *(ip_src++);
|
||||
sum += *(ip_src++);
|
||||
sum += *(ip_src++);
|
||||
sum += *(ip_src++);
|
||||
sum += *(ip_src++);
|
||||
sum += *(ip_src++);
|
||||
sum += *(ip_src++);
|
||||
sum += *ip_src;
|
||||
sum += *(ip_dst++);
|
||||
sum += *(ip_dst++);
|
||||
sum += *(ip_dst++);
|
||||
sum += *(ip_dst++);
|
||||
sum += *(ip_dst++);
|
||||
sum += *(ip_dst++);
|
||||
sum += *(ip_dst++);
|
||||
sum += *ip_dst;
|
||||
sum += htons(IPPROTO_TCP);
|
||||
sum += htons(length);
|
||||
|
||||
// Add the carries
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
|
||||
// Return the one's complement of sum
|
||||
return (uint16_t)(~sum);
|
||||
}
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
tcp->check = 0;
|
||||
tcp->check = tcp6_checksum(tcp,len,src_addr,dest_addr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fill_tcphdr(struct tcphdr *tcp, uint8_t tcp_flags, uint32_t seq, uint32_t ack_seq, enum tcp_fooling_mode fooling, uint16_t nsport, uint16_t ndport)
|
||||
{
|
||||
char *tcpopt = (char*)(tcp+1);
|
||||
memset(tcp,0,sizeof(*tcp));
|
||||
tcp->source = nsport;
|
||||
tcp->dest = ndport;
|
||||
tcp->seq = seq;
|
||||
tcp->ack_seq = ack_seq;
|
||||
tcp->doff = 5;
|
||||
*((uint8_t*)tcp+13)= tcp_flags;
|
||||
tcp->window = htons(65535);
|
||||
if (fooling==TCP_FOOL_MD5SIG)
|
||||
{
|
||||
tcp->doff += 5; // +20 bytes
|
||||
tcpopt[0] = 19; // kind
|
||||
tcpopt[1] = 18; // len
|
||||
*(uint32_t*)(tcpopt+2)=random();
|
||||
*(uint32_t*)(tcpopt+6)=random();
|
||||
*(uint32_t*)(tcpopt+10)=random();
|
||||
*(uint32_t*)(tcpopt+14)=random();
|
||||
tcpopt[18] = 0; // end
|
||||
tcpopt[19] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rawsend_sock=-1;
|
||||
void rawsend_cleanup()
|
||||
{
|
||||
if (rawsend_sock!=-1)
|
||||
{
|
||||
close(rawsend_sock);
|
||||
rawsend_sock=-1;
|
||||
}
|
||||
}
|
||||
static void rawsend_socket(int family,uint32_t fwmark)
|
||||
{
|
||||
if (rawsend_sock==-1)
|
||||
{
|
||||
int yes=1,pri=6;
|
||||
rawsend_sock = socket(family, SOCK_RAW, IPPROTO_RAW);
|
||||
if (rawsend_sock==-1)
|
||||
perror("rawsend: socket()");
|
||||
else if (setsockopt(rawsend_sock, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_MARK)");
|
||||
rawsend_cleanup();
|
||||
}
|
||||
else if (setsockopt(rawsend_sock, SOL_SOCKET, SO_PRIORITY, &pri, sizeof(pri)) == -1)
|
||||
{
|
||||
perror("rawsend: setsockopt(SO_PRIORITY)");
|
||||
rawsend_cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len)
|
||||
{
|
||||
rawsend_socket(dst->sa_family,fwmark);
|
||||
if (rawsend_sock==-1) return false;
|
||||
|
||||
int salen = dst->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_storage dst2;
|
||||
memcpy(&dst2,dst,salen);
|
||||
if (dst->sa_family==AF_INET6)
|
||||
((struct sockaddr_in6 *)&dst2)->sin6_port = 0; // or will be EINVAL
|
||||
|
||||
int bytes = sendto(rawsend_sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
||||
if (bytes==-1)
|
||||
{
|
||||
perror("rawsend: sendto");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool prepare_tcp_segment4(
|
||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||
uint8_t tcp_flags,
|
||||
uint32_t seq, uint32_t ack_seq,
|
||||
uint8_t ttl,
|
||||
enum tcp_fooling_mode fooling,
|
||||
const void *data, uint16_t len,
|
||||
char *buf, size_t *buflen)
|
||||
{
|
||||
uint16_t tcpoptlen = 0;
|
||||
if (fooling==TCP_FOOL_MD5SIG) tcpoptlen=20;
|
||||
uint16_t pktlen = sizeof(struct iphdr) + sizeof(struct tcphdr) + tcpoptlen + len;
|
||||
if (pktlen>*buflen)
|
||||
{
|
||||
fprintf(stderr,"prepare_tcp_segment : packet len cannot exceed %zu\n",*buflen);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct iphdr *ip = (struct iphdr*) buf;
|
||||
struct tcphdr *tcp = (struct tcphdr*) (ip+1);
|
||||
|
||||
ip->frag_off = 0;
|
||||
ip->version = 4;
|
||||
ip->ihl = 5;
|
||||
ip->tot_len = htons(pktlen);
|
||||
ip->id = 0;
|
||||
ip->ttl = ttl;
|
||||
ip->protocol = IPPROTO_TCP;
|
||||
ip->saddr = src->sin_addr.s_addr;
|
||||
ip->daddr = dst->sin_addr.s_addr;
|
||||
|
||||
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin_port,dst->sin_port);
|
||||
|
||||
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
|
||||
tcp_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,ip->saddr,ip->daddr);
|
||||
if (fooling==TCP_FOOL_BADSUM) tcp->check^=0xBEAF;
|
||||
|
||||
*buflen = pktlen;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool prepare_tcp_segment6(
|
||||
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
|
||||
uint8_t tcp_flags,
|
||||
uint32_t seq, uint32_t ack_seq,
|
||||
uint8_t ttl,
|
||||
enum tcp_fooling_mode fooling,
|
||||
const void *data, uint16_t len,
|
||||
char *buf, size_t *buflen)
|
||||
{
|
||||
uint16_t tcpoptlen = 0;
|
||||
if (fooling==TCP_FOOL_MD5SIG) tcpoptlen=20;
|
||||
uint16_t payloadlen = sizeof(struct tcphdr) + tcpoptlen + len;
|
||||
uint16_t pktlen = sizeof(struct ip6_hdr) + payloadlen;
|
||||
if (pktlen>*buflen)
|
||||
{
|
||||
fprintf(stderr,"prepare_tcp_segment : packet len cannot exceed %zu\n",*buflen);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr*) buf;
|
||||
struct tcphdr *tcp = (struct tcphdr*) (ip6+1);
|
||||
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(payloadlen);
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_TCP;
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
|
||||
ip6->ip6_src = src->sin6_addr;
|
||||
ip6->ip6_dst = dst->sin6_addr;
|
||||
|
||||
fill_tcphdr(tcp,tcp_flags,seq,ack_seq,fooling,src->sin6_port,dst->sin6_port);
|
||||
|
||||
memcpy((char*)tcp+sizeof(struct tcphdr)+tcpoptlen,data,len);
|
||||
tcp6_fix_checksum(tcp,sizeof(struct tcphdr)+tcpoptlen+len,&ip6->ip6_src,&ip6->ip6_dst);
|
||||
if (fooling==TCP_FOOL_BADSUM) tcp->check^=0xBEAF;
|
||||
|
||||
*buflen = pktlen;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prepare_tcp_segment(
|
||||
const struct sockaddr *src, const struct sockaddr *dst,
|
||||
uint8_t tcp_flags,
|
||||
uint32_t seq, uint32_t ack_seq,
|
||||
uint8_t ttl,
|
||||
enum tcp_fooling_mode fooling,
|
||||
const void *data, uint16_t len,
|
||||
char *buf, size_t *buflen)
|
||||
{
|
||||
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
|
||||
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,seq,ack_seq,ttl,fooling,data,len,buf,buflen) :
|
||||
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
|
||||
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,seq,ack_seq,ttl,fooling,data,len,buf,buflen) :
|
||||
false;
|
||||
}
|
||||
|
||||
|
||||
void extract_endpoints(const struct iphdr *iphdr,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst)
|
||||
{
|
||||
if (iphdr)
|
||||
{
|
||||
struct sockaddr_in *si = (struct sockaddr_in*)dst;
|
||||
si->sin_family = AF_INET;
|
||||
si->sin_port = tcphdr->dest;
|
||||
si->sin_addr.s_addr = iphdr->daddr;
|
||||
|
||||
si = (struct sockaddr_in*)src;
|
||||
si->sin_family = AF_INET;
|
||||
si->sin_port = tcphdr->source;
|
||||
si->sin_addr.s_addr = iphdr->saddr;
|
||||
}
|
||||
else if (ip6hdr)
|
||||
{
|
||||
struct sockaddr_in6 *si = (struct sockaddr_in6*)dst;
|
||||
si->sin6_family = AF_INET6;
|
||||
si->sin6_port = tcphdr->dest;
|
||||
si->sin6_addr = ip6hdr->ip6_dst;
|
||||
si->sin6_flowinfo = 0;
|
||||
si->sin6_scope_id = 0;
|
||||
|
||||
si = (struct sockaddr_in6*)src;
|
||||
si->sin6_family = AF_INET6;
|
||||
si->sin6_port = tcphdr->source;
|
||||
si->sin6_addr = ip6hdr->ip6_src;
|
||||
si->sin6_flowinfo = 0;
|
||||
si->sin6_scope_id = 0;
|
||||
}
|
||||
}
|
51
nfq/darkmagic.h
Normal file
51
nfq/darkmagic.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
uint16_t tcp_checksum(const void *buff, int len, in_addr_t src_addr, in_addr_t dest_addr);
|
||||
void tcp_fix_checksum(struct tcphdr *tcp,int len, in_addr_t src_addr, in_addr_t dest_addr);
|
||||
uint16_t tcp6_checksum(const void *buff, int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp,int len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);
|
||||
|
||||
enum tcp_fooling_mode {
|
||||
TCP_FOOL_NONE=0,
|
||||
TCP_FOOL_MD5SIG=1,
|
||||
TCP_FOOL_BADSUM=2
|
||||
};
|
||||
bool prepare_tcp_segment4(
|
||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||
uint8_t tcp_flags,
|
||||
uint32_t seq, uint32_t ack_seq,
|
||||
uint8_t ttl,
|
||||
enum tcp_fooling_mode fooling,
|
||||
const void *data, uint16_t len,
|
||||
char *buf, size_t *buflen);
|
||||
bool prepare_tcp_segment6(
|
||||
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
|
||||
uint8_t tcp_flags,
|
||||
uint32_t seq, uint32_t ack_seq,
|
||||
uint8_t ttl,
|
||||
enum tcp_fooling_mode fooling,
|
||||
const void *data, uint16_t len,
|
||||
char *buf, size_t *buflen);
|
||||
bool prepare_tcp_segment(
|
||||
const struct sockaddr *src, const struct sockaddr *dst,
|
||||
uint8_t tcp_flags,
|
||||
uint32_t seq, uint32_t ack_seq,
|
||||
uint8_t ttl,
|
||||
enum tcp_fooling_mode fooling,
|
||||
const void *data, uint16_t len,
|
||||
char *buf, size_t *buflen);
|
||||
|
||||
void extract_endpoints(const struct iphdr *iphdr,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
|
||||
|
||||
// auto creates internal socket and uses it for subsequent calls
|
||||
bool rawsend(struct sockaddr* dst,uint32_t fwmark,const void *data,size_t len);
|
||||
// cleans up socket autocreated by rawsend
|
||||
void rawsend_cleanup();
|
82
nfq/gzip.c
Normal file
82
nfq/gzip.c
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "gzip.h"
|
||||
|
||||
#define ZCHUNK 16384
|
||||
#define BUFMIN 128
|
||||
#define BUFCHUNK (1024*128)
|
||||
|
||||
int z_readfile(FILE *F,char **buf,size_t *size)
|
||||
{
|
||||
z_stream zs;
|
||||
int r;
|
||||
unsigned char in[ZCHUNK];
|
||||
size_t bufsize;
|
||||
void *newbuf;
|
||||
|
||||
memset(&zs,0,sizeof(zs));
|
||||
|
||||
*buf = NULL;
|
||||
bufsize=*size=0;
|
||||
|
||||
r=inflateInit2(&zs,47);
|
||||
if (r != Z_OK) return r;
|
||||
|
||||
do
|
||||
{
|
||||
zs.avail_in = fread(in, 1, sizeof(in), F);
|
||||
if (ferror(F))
|
||||
{
|
||||
r = Z_ERRNO;
|
||||
goto zerr;
|
||||
}
|
||||
if (!zs.avail_in) break;
|
||||
zs.next_in = in;
|
||||
do
|
||||
{
|
||||
if ((bufsize-*size)<BUFMIN)
|
||||
{
|
||||
bufsize += BUFCHUNK;
|
||||
newbuf = *buf ? realloc(*buf,bufsize) : malloc(bufsize);
|
||||
if (!newbuf)
|
||||
{
|
||||
r = Z_MEM_ERROR;
|
||||
goto zerr;
|
||||
}
|
||||
*buf = newbuf;
|
||||
}
|
||||
zs.avail_out = bufsize - *size;
|
||||
zs.next_out = (unsigned char*)(*buf + *size);
|
||||
r = inflate(&zs, Z_NO_FLUSH);
|
||||
if (r!=Z_OK && r!=Z_STREAM_END) goto zerr;
|
||||
*size = bufsize - zs.avail_out;
|
||||
} while (r==Z_OK && zs.avail_in);
|
||||
} while (r==Z_OK);
|
||||
|
||||
if (*size<bufsize)
|
||||
{
|
||||
// free extra space
|
||||
if (newbuf = realloc(*buf,*size)) *buf=newbuf;
|
||||
}
|
||||
|
||||
inflateEnd(&zs);
|
||||
return Z_OK;
|
||||
|
||||
zerr:
|
||||
inflateEnd(&zs);
|
||||
if (*buf)
|
||||
{
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool is_gzip(FILE* F)
|
||||
{
|
||||
unsigned char magic[2];
|
||||
bool b = !fseek(F,0,SEEK_SET) && fread(magic, 1, 2, F)==2 && magic[0]==0x1F && magic[1]==0x8B;
|
||||
fseek(F,0,SEEK_SET);
|
||||
return b;
|
||||
}
|
8
nfq/gzip.h
Normal file
8
nfq/gzip.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
int z_readfile(FILE *F,char **buf,size_t *size);
|
||||
bool is_gzip(FILE* F);
|
112
nfq/hostlist.c
Normal file
112
nfq/hostlist.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <stdio.h>
|
||||
#include "hostlist.h"
|
||||
#include "gzip.h"
|
||||
|
||||
|
||||
static bool addpool(strpool **hostlist, char **s, char *end)
|
||||
{
|
||||
char *p;
|
||||
|
||||
// advance until eol lowering all chars
|
||||
for (p = *s; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
|
||||
if (!StrPoolAddStrLen(hostlist, *s, p-*s))
|
||||
{
|
||||
StrPoolDestroy(hostlist);
|
||||
*hostlist = NULL;
|
||||
return false;
|
||||
}
|
||||
// advance to the next line
|
||||
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
|
||||
*s = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LoadHostList(strpool **hostlist, char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
size_t zsize;
|
||||
int ct = 0;
|
||||
FILE *F;
|
||||
int r;
|
||||
|
||||
if (*hostlist)
|
||||
{
|
||||
StrPoolDestroy(hostlist);
|
||||
*hostlist = NULL;
|
||||
}
|
||||
|
||||
if (!(F = fopen(filename, "rb")))
|
||||
{
|
||||
fprintf(stderr, "Could not open %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_gzip(F))
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
{
|
||||
printf("zlib compression detected. uncompressed size : %zu\n", zsize);
|
||||
|
||||
p = zbuf;
|
||||
e = zbuf + zsize;
|
||||
while(p<e)
|
||||
{
|
||||
if (!addpool(hostlist,&p,e))
|
||||
{
|
||||
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
|
||||
free(zbuf);
|
||||
return false;
|
||||
}
|
||||
ct++;
|
||||
}
|
||||
free(zbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "zlib decompression failed : result %d\n",r);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("loading plain text list\n");
|
||||
|
||||
while (fgets(s, 256, F))
|
||||
{
|
||||
p = s;
|
||||
if (!addpool(hostlist,&p,p+strlen(p)))
|
||||
{
|
||||
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
|
||||
fclose(F);
|
||||
return false;
|
||||
}
|
||||
ct++;
|
||||
}
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
printf("Loaded %d hosts from %s\n", ct, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SearchHostList(strpool *hostlist, const char *host, bool debug)
|
||||
{
|
||||
if (hostlist)
|
||||
{
|
||||
const char *p = host;
|
||||
bool bInHostList;
|
||||
while (p)
|
||||
{
|
||||
bInHostList = StrPoolCheckStr(hostlist, p);
|
||||
if (debug) printf("Hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
|
||||
if (bInHostList) return true;
|
||||
p = strchr(p, '.');
|
||||
if (p) p++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
7
nfq/hostlist.h
Normal file
7
nfq/hostlist.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "strpool.h"
|
||||
|
||||
bool LoadHostList(strpool **hostlist, char *filename);
|
||||
bool SearchHostList(strpool *hostlist, const char *host,bool debug);
|
1041
nfq/nfqws.c
Normal file
1041
nfq/nfqws.c
Normal file
File diff suppressed because it is too large
Load Diff
128
nfq/sec.c
Normal file
128
nfq/sec.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "sec.h"
|
||||
#include <sys/prctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
bool setpcap(cap_value_t *caps, int ncaps)
|
||||
{
|
||||
cap_t capabilities;
|
||||
|
||||
if (!(capabilities = cap_init()))
|
||||
return false;
|
||||
|
||||
if (ncaps && (cap_set_flag(capabilities, CAP_PERMITTED, ncaps, caps, CAP_SET) ||
|
||||
cap_set_flag(capabilities, CAP_EFFECTIVE, ncaps, caps, CAP_SET)))
|
||||
{
|
||||
cap_free(capabilities);
|
||||
return false;
|
||||
}
|
||||
if (cap_set_proc(capabilities))
|
||||
{
|
||||
cap_free(capabilities);
|
||||
return false;
|
||||
}
|
||||
cap_free(capabilities);
|
||||
return true;
|
||||
}
|
||||
int getmaxcap()
|
||||
{
|
||||
int maxcap = CAP_LAST_CAP;
|
||||
FILE *F = fopen("/proc/sys/kernel/cap_last_cap", "r");
|
||||
if (F)
|
||||
{
|
||||
int n = fscanf(F, "%d", &maxcap);
|
||||
fclose(F);
|
||||
}
|
||||
return maxcap;
|
||||
|
||||
}
|
||||
bool dropcaps()
|
||||
{
|
||||
// must have CAP_SETPCAP at the end. its required to clear bounding set
|
||||
cap_value_t cap_values[] = { CAP_NET_ADMIN,CAP_NET_RAW,CAP_SETPCAP };
|
||||
int capct = sizeof(cap_values) / sizeof(*cap_values);
|
||||
int maxcap = getmaxcap();
|
||||
|
||||
if (setpcap(cap_values, capct))
|
||||
{
|
||||
for (int cap = 0; cap <= maxcap; cap++)
|
||||
{
|
||||
if (cap_drop_bound(cap))
|
||||
{
|
||||
fprintf(stderr, "could not drop cap %d\n", cap);
|
||||
perror("cap_drop_bound");
|
||||
}
|
||||
}
|
||||
}
|
||||
// now without CAP_SETPCAP
|
||||
if (!setpcap(cap_values, capct - 1))
|
||||
{
|
||||
perror("setpcap");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool droproot(uid_t uid, gid_t gid)
|
||||
{
|
||||
if (uid || gid)
|
||||
{
|
||||
if (prctl(PR_SET_KEEPCAPS, 1L))
|
||||
{
|
||||
perror("prctl(PR_SET_KEEPCAPS): ");
|
||||
return false;
|
||||
}
|
||||
if (setgid(gid))
|
||||
{
|
||||
perror("setgid: ");
|
||||
return false;
|
||||
}
|
||||
if (setuid(uid))
|
||||
{
|
||||
perror("setuid: ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return dropcaps();
|
||||
}
|
||||
|
||||
void daemonize()
|
||||
{
|
||||
int pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
perror("fork: ");
|
||||
exit(2);
|
||||
}
|
||||
else if (pid != 0)
|
||||
exit(0);
|
||||
|
||||
if (setsid() == -1)
|
||||
exit(2);
|
||||
if (chdir("/") == -1)
|
||||
exit(2);
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
/* redirect fd's 0,1,2 to /dev/null */
|
||||
open("/dev/null", O_RDWR);
|
||||
int fd;
|
||||
/* stdin */
|
||||
fd = dup(0);
|
||||
/* stdout */
|
||||
fd = dup(0);
|
||||
/* stderror */
|
||||
}
|
||||
|
||||
bool writepid(const char *filename)
|
||||
{
|
||||
FILE *F;
|
||||
if (!(F = fopen(filename, "w")))
|
||||
return false;
|
||||
fprintf(F, "%d", getpid());
|
||||
fclose(F);
|
||||
return true;
|
||||
}
|
12
nfq/sec.h
Normal file
12
nfq/sec.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/capability.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool setpcap(cap_value_t *caps, int ncaps);
|
||||
int getmaxcap();
|
||||
bool dropcaps();
|
||||
bool droproot(uid_t uid, gid_t gid);
|
||||
void daemonize();
|
||||
bool writepid(const char *filename);
|
76
nfq/strpool.c
Normal file
76
nfq/strpool.c
Normal file
@@ -0,0 +1,76 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "strpool.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#undef uthash_nonfatal_oom
|
||||
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
||||
|
||||
static bool oom=false;
|
||||
static void ut_oom_recover(strpool *elem)
|
||||
{
|
||||
oom=true;
|
||||
}
|
||||
|
||||
// for zero terminated strings
|
||||
bool StrPoolAddStr(strpool **pp,const char *s)
|
||||
{
|
||||
strpool *elem;
|
||||
if (!(elem = (strpool*)malloc(sizeof(strpool))))
|
||||
return false;
|
||||
if (!(elem->str = strdup(s)))
|
||||
{
|
||||
free(elem);
|
||||
return false;
|
||||
}
|
||||
oom = false;
|
||||
HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem );
|
||||
if (oom)
|
||||
{
|
||||
free(elem->str);
|
||||
free(elem);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// for not zero terminated strings
|
||||
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen)
|
||||
{
|
||||
strpool *elem;
|
||||
if (!(elem = (strpool*)malloc(sizeof(strpool))))
|
||||
return false;
|
||||
if (!(elem->str = malloc(slen+1)))
|
||||
{
|
||||
free(elem);
|
||||
return false;
|
||||
}
|
||||
memcpy(elem->str,s,slen);
|
||||
elem->str[slen]=0;
|
||||
oom = false;
|
||||
HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem );
|
||||
if (oom)
|
||||
{
|
||||
free(elem->str);
|
||||
free(elem);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StrPoolCheckStr(strpool *p,const char *s)
|
||||
{
|
||||
strpool *elem;
|
||||
HASH_FIND_STR( p, s, elem);
|
||||
return elem!=NULL;
|
||||
}
|
||||
|
||||
void StrPoolDestroy(strpool **p)
|
||||
{
|
||||
strpool *elem,*tmp;
|
||||
HASH_ITER(hh, *p, elem, tmp) {
|
||||
free(elem->str);
|
||||
HASH_DEL(*p, elem);
|
||||
free(elem);
|
||||
}
|
||||
*p = NULL;
|
||||
}
|
19
nfq/strpool.h
Normal file
19
nfq/strpool.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
#define HASH_FUNCTION HASH_BER
|
||||
#include "uthash.h"
|
||||
|
||||
typedef struct strpool {
|
||||
char *str; /* key */
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
} strpool;
|
||||
|
||||
void StrPoolDestroy(strpool **p);
|
||||
bool StrPoolAddStr(strpool **pp,const char *s);
|
||||
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
|
||||
bool StrPoolCheckStr(strpool *p,const char *s);
|
1217
nfq/uthash.h
Normal file
1217
nfq/uthash.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user