/* 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. */
+/* THIS SOFTWARE IS PROVIDED BY THE 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 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 (c) 2006-2008 the Authors */
+/* see AUTHORS and source files for details */
/******************************************************************************/
/*
#include "server.h"
#define DAEMON_NAME "pfix-srsd"
-#define DAEMON_VERSION "0.4"
+#define DAEMON_VERSION "0.5"
#define DEFAULT_ENCODER_PORT 10001
#define DEFAULT_DECODER_PORT 10002
#define RUNAS_USER "nobody"
typedef struct srs_config_t {
srs_t* srs;
const char* domain;
+ int domainlen;
+ int ignore_ext;
} srs_config_t;
/* Processing {{{1
*/
-void urldecode(char *s, char *end)
+char *urldecode(char *s, char *end)
{
char *p = s;
*s++ = *p++;
}
- *s++ = '\0';
+ *s = '\0';
+ return s;
}
int process_srs(client_t *srsd, void* vconfig)
}
if (strncmp("get ", ibuf->data, 4)) {
- err("bad request, not starting with \"get \"");
+ err("bad request, not starting with \"get \"");
return -1;
}
for (q = nl++; q >= p && isspace(*q); *q-- = '\0');
if (p == q) {
- buffer_addstr(&*obuf, "400 empty request ???\n");
+ buffer_addstr(obuf, "400 empty request ???\n");
warn("empty request");
goto skip;
}
- urldecode(p, q);
+ q = urldecode(p, q);
if (decoder) {
+ if (config->ignore_ext) {
+ int dlen = config->domainlen;
+
+ if (q - p <= dlen || q[-1 - dlen] != '@' ||
+ memcmp(q - dlen, config->domain, dlen))
+ {
+ buffer_addstr(obuf, "200 ");
+ buffer_add(obuf, p, q - p);
+ buffer_addch(obuf, '\n');
+ goto skip;
+ }
+ }
err = srs_reverse(config->srs, buf, ssizeof(buf), p);
} else {
err = srs_forward(config->srs, buf, ssizeof(buf), p, config->domain);
}
if (err == 0) {
- buffer_addstr(&*obuf, "200 ");
- buffer_addstr(&*obuf, buf);
+ buffer_addstr(obuf, "200 ");
+ buffer_addstr(obuf, buf);
} else {
switch (SRS_ERROR_TYPE(err)) {
case SRS_ERRTYPE_SRS:
case SRS_ERRTYPE_SYNTAX:
- buffer_addstr(&*obuf, "500 ");
+ buffer_addstr(obuf, "500 ");
break;
default:
- buffer_addstr(&*obuf, "400 ");
+ buffer_addstr(obuf, "400 ");
break;
}
buffer_addstr(obuf, srs_strerror(err));
" (default: "STR(DEFAULT_DECODER_PORT)")\n"
" -p <pidfile> file to write our pid to\n"
" -u unsafe mode: don't drop privilegies\n"
+ " -I do not touch mails outside of \"domain\" in decoding mode\n"
" -f stay in foreground\n"
, stderr);
}
int port_dec = DEFAULT_DECODER_PORT;
const char *pidfile = NULL;
- for (int c = 0; (c = getopt(argc, argv, "hfu" "e:d:p:")) >= 0; ) {
+ for (int c = 0; (c = getopt(argc, argv, "hfuI" "e:d:p:")) >= 0; ) {
switch (c) {
case 'e':
port_enc = atoi(optarg);
case 'u':
unsafe = true;
break;
+ case 'I':
+ config.ignore_ext = true;
+ break;
default:
usage();
return EXIT_FAILURE;
info("%s v%s...", DAEMON_NAME, DAEMON_VERSION);
config.domain = argv[optind];
+ config.domainlen = strlen(config.domain);
config.srs = srs_read_secrets(argv[optind + 1]);
if (!config.srs
|| common_setup(pidfile, unsafe, RUNAS_USER, RUNAS_GROUP,