From b8b6ac5a6d545a000077eed217c221c7eeda2a84 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 27 Aug 2007 23:30:04 +0200 Subject: [PATCH] Lot of work on postlicyd, also make the repository a general postfix-addons repo. Import srs-c as srsd, as I intend to enhance it a lot. Signed-off-by: Pierre Habouzit --- .gitignore | 6 +- Makefile | 23 ++-- postlicyd.h => common.h | 0 daemon.c | 2 +- postfix.c | 2 +- postlicyd.c | 2 +- qsort.c | 260 ++++++++++++++++++++++++++++++++++++++++ rbl.c | 214 +++++++++++++++++++++++++++++++++ rbl.h | 47 ++++++++ srsd.c | 216 +++++++++++++++++++++++++++++++++ str.h | 8 ++ tst-rbl.c | 52 ++++++++ 12 files changed, 819 insertions(+), 13 deletions(-) rename postlicyd.h => common.h (100%) create mode 100644 qsort.c create mode 100644 rbl.c create mode 100644 rbl.h create mode 100644 srsd.c create mode 100644 tst-rbl.c diff --git a/.gitignore b/.gitignore index abffbe0..fc954d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ -tokens.[hc] +/tokens.[hc] -postlicyd +/postlicyd +/tst-rbl +/srsd *.o .tags diff --git a/Makefile b/Makefile index 117f80d..329455c 100644 --- a/Makefile +++ b/Makefile @@ -33,18 +33,25 @@ LDFLAGS += -Wl,--warn-common include mk/cflags.mk -CFLAGS += --std=gnu99 -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 $(shell pkg-config --cflags lua5.1) +CFLAGS += --std=gnu99 -D_GNU_SOURCE -PROGRAMS = postlicyd +PROGRAMS = postlicyd srsd +TESTS = tst-rbl GENERATED = tokens.h tokens.c postlicyd_SOURCES = \ - str.h buffer.h daemon.h postfix.h \ - str.c buffer.c daemon.c postfix.c \ + str.h buffer.h daemon.h rbl.h postfix.h \ + str.c buffer.c daemon.c rbl.c postfix.c \ postlicyd.c $(GENERATED) +postlicyd_LIBADD = -lpthread -postlicyd_LIBADD = -lpthread $(shell pkg-config --libs lua5.1) +srsd_SOURCES = \ + str.h daemon.h srsd.h \ + str.c daemon.c srsd.c +srsd_LIBADD = -lsrs2 + +tst-rbl_SOURCES = tst-rbl.c # RULES ###################################################################{{{ @@ -80,9 +87,9 @@ headers: .SECONDEXPANSION: -$(PROGRAMS): $$(patsubst %.c,.%.o,$$($$@_SOURCES)) Makefile - $(CC) -o $@ $(CFLAGS) $(filter %.o,$^) $(LDFLAGS) $($@_LIBADD) $(filter %.a,$^) +$(PROGRAMS) $(TESTS): $$(patsubst %.c,.%.o,$$($$@_SOURCES)) Makefile + $(CC) -o $@ $(CFLAGS) $($@_CFLAGS) $(filter %.o,$^) $(LDFLAGS) $($@_LIBADD) $(filter %.a,$^) --include $(foreach p,$(PROGRAMS),$(patsubst %.c,.%.dep,$(filter %.c,$($p_SOURCES)))) +-include $(foreach p,$(PROGRAMS) $(TESTS),$(patsubst %.c,.%.dep,$(filter %.c,$($p_SOURCES)))) ###########################################################################}}} diff --git a/postlicyd.h b/common.h similarity index 100% rename from postlicyd.h rename to common.h diff --git a/daemon.c b/daemon.c index ec8be65..d3dc00d 100644 --- a/daemon.c +++ b/daemon.c @@ -35,7 +35,7 @@ #include -#include "postlicyd.h" +#include "common.h" #include "daemon.h" int tcp_listen(const struct sockaddr *addr, socklen_t len) diff --git a/postfix.c b/postfix.c index 4086deb..018bd25 100644 --- a/postfix.c +++ b/postfix.c @@ -33,7 +33,7 @@ * Copyright © 2006-2007 Pierre Habouzit */ -#include "postlicyd.h" +#include "common.h" #include "postfix.h" #include "buffer.h" #include "tokens.h" diff --git a/postlicyd.c b/postlicyd.c index f6f3ccc..e9eb1c2 100644 --- a/postlicyd.c +++ b/postlicyd.c @@ -37,7 +37,7 @@ #include #include -#include "postlicyd.h" +#include "common.h" static sig_atomic_t cleanexit = false; static sig_atomic_t sigint = false; diff --git a/qsort.c b/qsort.c new file mode 100644 index 0000000..a24a709 --- /dev/null +++ b/qsort.c @@ -0,0 +1,260 @@ +/******************************************************************************/ +/* postlicyd: a postfix policy daemon with a lot of features */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* $Id: qsort.c,v 1.3 2003/04/11 12:31:46 mjt Exp $ + * Adopted from GNU glibc by Mjt. + * See stdlib/qsort.c in glibc */ + +/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Douglas C. Schmidt (schmidt@ics.uci.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Usage: + * first, define the following: + * QSORT_TYPE - type of array elements + * QSORT_BASE - pointer to array + * QSORT_NELT - number of elements in the array (must not be 0) + * QSORT_LT - QSORT_LT(a,b) should return true if *a < *b + * and second, just #include this file into the place you want it. + * Some C code will be inserted into that place, to sort array defined + * by QSORT_TYPE, QSORT_BASE, QSORT_NELT and comparision routine QSORT_LT. + */ + +/* Swap two items pointed to by A and B using temporary buffer t. */ +#define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ +#define _QSORT_MAX_THRESH 4 + +/* Stack node declarations used to store unfulfilled partition obligations + * (inlined in QSORT). +typedef struct { + TYPE *_lo, *_hi; +} qsort_stack_node; + */ + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type unsigned, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(unsigned). */ +#define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) +#define _QSORT_PUSH(top, low, high) \ + (((top->_lo = (low)), (top->_hi = (high)), ++top)) +#define _QSORT_POP(low, high, top) \ + ((--top, (low = top->_lo), (high = top->_hi))) +#define _QSORT_STACK_NOT_EMPTY (_stack < _top) + + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + + +{ + QSORT_TYPE *const _base = (QSORT_BASE); + const unsigned _elems = (QSORT_NELT); + QSORT_TYPE _hold; + + if (_elems > _QSORT_MAX_THRESH) { + QSORT_TYPE *_lo = _base; + QSORT_TYPE *_hi = _lo + _elems - 1; + struct { + QSORT_TYPE *_hi, *_lo; + } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; + + while (_QSORT_STACK_NOT_EMPTY) { + QSORT_TYPE *_left_ptr, *_right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); + + if (QSORT_LT (_mid, _lo)) + _QSORT_SWAP (_mid, _lo, _hold); + if (QSORT_LT (_hi, _mid)) + _QSORT_SWAP (_mid, _hi, _hold); + else + goto _jump_over; + if (QSORT_LT (_mid, _lo)) + _QSORT_SWAP (_mid, _lo, _hold); + _jump_over:; + + _left_ptr = _lo + 1; + _right_ptr = _hi - 1; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do { + while (QSORT_LT (_left_ptr, _mid)) + ++_left_ptr; + + while (QSORT_LT (_mid, _right_ptr)) + --_right_ptr; + + if (_left_ptr < _right_ptr) { + _QSORT_SWAP (_left_ptr, _right_ptr, _hold); + if (_mid == _left_ptr) + _mid = _right_ptr; + else if (_mid == _right_ptr) + _mid = _left_ptr; + ++_left_ptr; + --_right_ptr; + } + else if (_left_ptr == _right_ptr) { + ++_left_ptr; + --_right_ptr; + break; + } + } while (_left_ptr <= _right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { + if (_hi - _left_ptr <= _QSORT_MAX_THRESH) + /* Ignore both small partitions. */ + _QSORT_POP (_lo, _hi, _top); + else + /* Ignore small left partition. */ + _lo = _left_ptr; + } + else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) + /* Ignore small right partition. */ + _hi = _right_ptr; + else if (_right_ptr - _lo > _hi - _left_ptr) { + /* Push larger left partition indices. */ + _QSORT_PUSH (_top, _lo, _right_ptr); + _lo = _left_ptr; + } + else { + /* Push larger right partition indices. */ + _QSORT_PUSH (_top, _left_ptr, _hi); + _hi = _right_ptr; + } + } + } + + /* Once the BASE array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE points to the + beginning of the array to sort, and END_PTR points at the very + last element in the array (*not* one beyond it!). */ + + + { + QSORT_TYPE *const _end_ptr = _base + _elems - 1; + QSORT_TYPE *_tmp_ptr = _base; + register QSORT_TYPE *_run_ptr; + QSORT_TYPE *_thresh; + + _thresh = _base + _QSORT_MAX_THRESH; + if (_thresh > _end_ptr) + _thresh = _end_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) + if (QSORT_LT (_run_ptr, _tmp_ptr)) + _tmp_ptr = _run_ptr; + + if (_tmp_ptr != _base) + _QSORT_SWAP (_tmp_ptr, _base, _hold); + + /* Insertion sort, running from left-hand-side + * up to right-hand-side. */ + + _run_ptr = _base + 1; + while (++_run_ptr <= _end_ptr) { + _tmp_ptr = _run_ptr - 1; + while (QSORT_LT (_run_ptr, _tmp_ptr)) + --_tmp_ptr; + + ++_tmp_ptr; + if (_tmp_ptr != _run_ptr) { + QSORT_TYPE *_trav = _run_ptr + 1; + while (--_trav >= _run_ptr) { + QSORT_TYPE *_hi, *_lo; + _hold = *_trav; + + for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) + *_hi = *_lo; + *_hi = _hold; + } + } + } + } +} diff --git a/rbl.c b/rbl.c new file mode 100644 index 0000000..599db63 --- /dev/null +++ b/rbl.c @@ -0,0 +1,214 @@ +/******************************************************************************/ +/* postlicyd: a postfix policy daemon with a lot of features */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* + * Copyright © 2007 Pierre Habouzit + */ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "rbl.h" +#include "str.h" + +#define IPv4_BITS 5 +#define IPv4_PREFIX(ip) ((uint32_t)(ip) >> IPv4_BITS) +#define IPv4_SUFFIX(ip) ((uint32_t)(ip) & ((1 << IPv4_BITS) - 1)) +#define NODE(db, i) ((db)->tree + (i)) +#ifndef DEBUG +#define DEBUG(...) +#endif + +enum { + BALANCED = 0, + LEFT_HEAVY = 1, + RIGHT_HEAVY = 2, +}; + +struct rbldb_t { + uint32_t len, size; + uint32_t *ips; +}; + +static int get_o(const char *s, const char **out) +{ + int res = 0; + + if (*s < '0' || *s > '9') + return -1; + + res = *s++ - '0'; + if (*s < '0' || *s > '9') + goto ok; + + res = res * 10 + *s++ - '0'; + if (*s < '0' || *s > '9') + goto ok; + + res = res * 10 + *s++ - '0'; + if (!(*s < '0' || *s > '9') || res < 100) + return -1; + + ok: + *out = s; + return res; +} + +static int parse_ipv4(const char *s, const char **out, uint32_t *ip) +{ + int o; + + o = get_o(s, &s); + if ((o & ~0xff) || *s++ != '.') + return -1; + *ip = o << 24; + + o = get_o(s, &s); + if ((o & ~0xff) || *s++ != '.') + return -1; + *ip |= o << 16; + + o = get_o(s, &s); + if ((o & ~0xff) || *s++ != '.') + return -1; + *ip |= o << 8; + + o = get_o(s, &s); + if (o & ~0xff) + return -1; + *ip |= o; + + *out = s; + return 0; +} + +rbldb_t *rbldb_create(const char *file) +{ + rbldb_t *db; + const char *map, *p, *end; + struct stat st; + int fd; + + fd = open(file, O_RDONLY, 0000); + if (fd < 0) { + UNIXERR("open"); + return NULL; + } + + if (fstat(fd, &st) < 0) { + UNIXERR("fstat"); + close(fd); + return NULL; + } + + p = map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { + UNIXERR("mmap"); + close(fd); + return NULL; + } + close(fd); + + end = map + st.st_size; + while (end > map && end[-1] != '\n') { + --end; + } + if (end != map + st.st_size) { + syslog(LOG_WARNING, "file %s miss a final \\n, ignoring last line", + file); + } + + db = p_new(rbldb_t, 1); + while (p < end) { + uint32_t ip; + + while (*p == ' ' || *p == '\t' || *p == '\r') + p++; + + if (parse_ipv4(p, &p, &ip) < 0) { + p = (char *)memchr(p, '\n', end - p) + 1; + } else { + if (db->len >= db->size) { + db->size += 64 * 1024; + p_realloc(&db->ips, db->size); + } + db->ips[db->len++] = ip; + } + } + munmap((void*)map, st.st_size); + + if (db->len) { +# define QSORT_TYPE uint32_t +# define QSORT_BASE db->ips +# define QSORT_NELT db->len +# define QSORT_LT(a,b) *a < *b +# include "qsort.c" + } + + syslog(LOG_INFO, "rbl %s loaded, %d IPs", file, db->len); + return db; +} + +void rbldb_delete(rbldb_t **db) +{ + if (*db) { + p_delete(&(*db)->ips); + p_delete(&(*db)); + } +} + +uint32_t rbldb_stats(rbldb_t *rbl) +{ + return rbl->len; +} + +bool rbldb_ipv4_lookup(rbldb_t *db, uint32_t ip) +{ + int l = 0, r = db->len; + + while (l < r) { + int i = (r + 1) / 2; + + if (db->ips[i] == ip) + return true; + + if (ip < db->ips[i]) { + r = i; + } else { + l = i + 1; + } + } + return false; +} diff --git a/rbl.h b/rbl.h new file mode 100644 index 0000000..bddea8f --- /dev/null +++ b/rbl.h @@ -0,0 +1,47 @@ +/******************************************************************************/ +/* postlicyd: a postfix policy daemon with a lot of features */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* + * Copyright © 2007 Pierre Habouzit + */ + +#ifndef POSTLICYD_RBL_H +#define POSTLICYD_RBL_H + +typedef struct rbldb_t rbldb_t; + +rbldb_t *rbldb_create(const char *file); +void rbldb_delete(rbldb_t **); + +uint32_t rbldb_stats(rbldb_t *rbl); +bool rbldb_ipv4_lookup(rbldb_t *rbl, uint32_t ip); + +#endif diff --git a/srsd.c b/srsd.c new file mode 100644 index 0000000..aca3f79 --- /dev/null +++ b/srsd.c @@ -0,0 +1,216 @@ +/******************************************************************************/ +/* postlicyd: a postfix policy daemon with a lot of features */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* + * Copyright © 2005-2007 Pierre Habouzit + */ + +#include +#include + +#include + +#include "common.h" +#include "mem.h" + +#define MAX_SIZE 0x10000 + +static char **read_sfile(char *sfile) +{ + int fd = -1; + int pos = 0; + int nb = 0; + int len = 0; + + char *buf = NULL; + char **res = NULL; + + struct stat stat_buf; + + if (stat(sfile, &stat_buf)) { + perror("stat"); + exit(1); + } + + if (stat_buf.st_size > MAX_SIZE) { + fprintf(stderr, "the secret file is too big\n"); + exit(1); + } + + buf = (char *)malloc(stat_buf.st_size+1); + buf[stat_buf.st_size] = 0; + + if ((fd = open(sfile, O_RDONLY)) < 0) { + perror("open"); + exit (1); + } + + for (;;) { + if ((nb = read(fd, &(buf[pos]), stat_buf.st_size)) < 0) { + if (errno == EINTR) + continue; + perror("read"); + exit(1); + } + pos += nb; + if (nb == 0 || pos == stat_buf.st_size) { + close(fd); + fd = -1; + break; + } + } + + for ( nb = pos = 0; pos < stat_buf.st_size ; pos++) + { + if ( buf[pos] == '\n' ) { + nb++; + buf[pos] = 0; + } + } + + res = p_new(char*, nb + 2); + + nb = pos = 0; + while (pos < stat_buf.st_size) + { + len = strlen(&(buf[pos])); + if (len) { + res[nb++] = &(buf[pos]); + } + pos += len+1; + } + + return res; +} + + +static char *encode(char * secret, char * sender, char * alias) +{ + int err = 0; + char *res = NULL; + srs_t *srs = srs_new(); + + srs_add_secret(srs, secret); + err = srs_forward_alloc(srs, &res, sender, alias); + + if (res == NULL) { + fprintf(stderr, "%s\n", srs_strerror(err)); + exit (1); + } + + return res; +} + +static char * decode(char * secret, char * secrets[], char * sender) +{ + int err = 0; + char * res = NULL; + srs_t * srs = srs_new(); + + if (secret) { + srs_add_secret(srs, secret); + } + + for (; secrets && secrets[err] != 0; err++) { + srs_add_secret(srs, secrets[err]); + } + + err = srs_reverse_alloc(srs, &res, sender); + + if (res == NULL) { + fprintf(stderr, "%s\n", srs_strerror(err)); + exit(1); + } + + return res; +} + +static void help(void) +{ + puts( + "Usage: srs-c [ -r | -d domain ] [ -s secret | -f sfile ] -e sender\n" + "Perform an SRS encoding / decoding\n" + "\n" + " -r perform an SRS decoding\n" + " -d domain use that domain (required for encoding)\n" + "\n" + " -s secret secret used in the encoding (sfile required if omitted)\n" + " -f sfile secret file for decoding. the first line is taken if -s omitted\n" + "\n" + " -e sender the sender address we want to encode/decode\n" + ); + exit (1); +} + +int main(int argc, char * argv[]) +{ + char *buf = NULL; + char *domain = NULL; + char *sender = NULL; + char *secret = NULL; + char *sfile = NULL; + + int opt = 0; + bool rev = false; + char **secr = NULL; + + while ((opt = getopt(argc, argv, "d:e:s:f:r")) != -1) + { + switch (opt) { + case 'd': domain = optarg; break; + case 'e': sender = optarg; break; + case 'f': sfile = optarg; break; + case 'r': rev = true; break; + case 's': secret = optarg; break; + } + } + + if ( !sender || !(secret||sfile) || !(rev||domain) ) { + help (); + } + + if (sfile) { + secr = read_sfile(sfile); + if (!secret && (!secr || !secr[0])) { + fprintf(stderr, "No secret given, and secret file is empty\n"); + exit (1); + } + } + + if (rev) { + buf = decode(secret, secr, sender); + } else { + buf = encode((secret ? secret : secr[0]), sender, domain); + } + + puts(buf); + return 0; +} diff --git a/str.h b/str.h index d51b603..447e6d4 100644 --- a/str.h +++ b/str.h @@ -338,6 +338,14 @@ static inline const char *m_strnextsp(const char *s) { return s; } +__attribute__((nonnull(1))) +static inline char *m_vstrnextsp(char *s) { + while (*s && !isspace((unsigned char)*s)) + s++; + return s; +} + + __attribute__((nonnull(1))) static inline const char *skipspaces(const char *s) { while (isspace((unsigned char)*s)) diff --git a/tst-rbl.c b/tst-rbl.c new file mode 100644 index 0000000..928e9ee --- /dev/null +++ b/tst-rbl.c @@ -0,0 +1,52 @@ +/******************************************************************************/ +/* postlicyd: a postfix policy daemon with a lot of features */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* + * Copyright © 2007 Pierre Habouzit + */ + +#define DEBUG(fmt, ...) \ + fprintf(stderr, "%s:%d:%s: "fmt"\n", \ + __FILE__, __LINE__, __func__, ##__VA_ARGS__) + +#include "common.h" +#include "rbl.c" + +int main(int argc, char *argv[]) +{ + if (argc > 1) { + rbldb_t *db = rbldb_create(argv[1]); + printf("loaded: %s, %d ips, %d o\n", argv[1], rbldb_stats(db), + rbldb_stats(db) * 4); + rbldb_delete(&db); + } + return 0; +} -- 2.20.1