X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=srsd.c;h=bdd98a8e2d88bbe85b20dd9574d643f44536a03b;hb=e3d9a582b6ff0bef16a6c1e7f506d9088379c77a;hp=4004c137d95cee696292e2452bf91bbe8e75bf61;hpb=28f081e506a26a01ea1b47f106ef77b05acc7d23;p=apps%2Fpfixtools.git diff --git a/srsd.c b/srsd.c index 4004c13..bdd98a8 100644 --- a/srsd.c +++ b/srsd.c @@ -1,5 +1,5 @@ /******************************************************************************/ -/* postlicyd: a postfix policy daemon with a lot of features */ +/* pfixtools: a collection of postfix related tools */ /* ~~~~~~~~~ */ /* ________________________________________________________________________ */ /* */ @@ -45,9 +45,12 @@ #include "mem.h" #include "buffer.h" -#define DAEMON_NAME "srsd" +#define DAEMON_NAME "pfix-srsd" #define DEFAULT_ENCODER_PORT 10000 #define DEFAULT_DECODER_PORT 10001 +#define RUNAS_USER "nobody" +#define RUNAS_GROUP "nogroup" + #define __tostr(x) #x #define STR(x) __tostr(x) @@ -80,29 +83,57 @@ static void srsd_delete(srsd_t **srsd) } } +void urldecode(char *s, char *end) +{ + char *p = s; + + while (*p) { + if (*p == '%' && end - p >= 3) { + int h = (hexval(p[1]) << 4) | hexval(p[2]); + + if (h >= 0) { + *s++ = h; + p += 3; + continue; + } + } + + *s++ = *p++; + } + *s++ = '\0'; +} + int process_srs(srs_t *srs, const char *domain, srsd_t *srsd) { while (srsd->ibuf.len > 4) { char buf[BUFSIZ], *p, *q, *nl; int err; + nl = strchr(srsd->ibuf.data + 4, '\n'); + if (!nl) { + if (srsd->ibuf.len > BUFSIZ) { + syslog(LOG_ERR, "unreasonnable amount of data without a \\n"); + return -1; + } + return 0; + } + if (strncmp("get ", srsd->ibuf.data, 4)) { syslog(LOG_ERR, "bad request, not starting with \"get \""); return -1; } - nl = strchr(srsd->ibuf.data + 4, '\n'); - if (!nl) - return 0; - for (p = srsd->ibuf.data + 4; p < nl && isspace(*p); p++); for (q = nl++; q >= p && isspace(*q); *q-- = '\0'); if (p == q) { + buffer_addstr(&srsd->obuf, "400 empty request ???\n"); syslog(LOG_WARNING, "empty request"); goto skip; } + urldecode(p, q); + if (srsd->decoder) { err = srs_reverse(srs, buf, ssizeof(buf), p); } else { @@ -112,7 +143,6 @@ int process_srs(srs_t *srs, const char *domain, srsd_t *srsd) if (err == 0) { buffer_addstr(&srsd->obuf, "200 "); buffer_addstr(&srsd->obuf, buf); - buffer_addstr(&srsd->obuf, "\r\n"); } else { switch (SRS_ERROR_TYPE(err)) { case SRS_ERRTYPE_SRS: @@ -124,8 +154,8 @@ int process_srs(srs_t *srs, const char *domain, srsd_t *srsd) break; } buffer_addstr(&srsd->obuf, srs_strerror(err)); - buffer_addstr(&srsd->obuf, "\r\n"); } + buffer_addch(&srsd->obuf, '\n'); skip: buffer_consume(&srsd->ibuf, nl - srsd->ibuf.data); @@ -145,7 +175,7 @@ int start_listener(int epollfd, int port, bool decoder) int sock; addr.sin_port = htons(port); - sock = tcp_listen((const struct sockaddr *)&addr, sizeof(addr)); + sock = tcp_listen_nonblock((const struct sockaddr *)&addr, sizeof(addr)); if (sock < 0) { return -1; } @@ -171,13 +201,13 @@ static int main_initialize(void) signal(SIGINT, &common_sighandler); signal(SIGTERM, &common_sighandler); signal(SIGHUP, &common_sighandler); + signal(SIGSEGV, &common_sighandler); syslog(LOG_INFO, "Starting..."); return 0; } static void main_shutdown(void) { - syslog(LOG_INFO, cleanexit ? "Stopping..." : "Unclean exit..."); closelog(); } @@ -186,12 +216,15 @@ module_exit(main_shutdown); void usage(void) { - fputs("usage: "DAEMON_NAME" [ -e ] [ -d ] domain secrets\n" + fputs("usage: "DAEMON_NAME" [options] domain secrets\n" "\n" + "Options:\n" " -e port to listen to for encoding requests\n" " (default: "STR(DEFAULT_ENCODER_PORT)")\n" " -d port to listen to for decoding requests\n" " (default: "STR(DEFAULT_DECODER_PORT)")\n" + " -p file to write our pid to\n" + " -u unsafe mode: don't drop privilegies\n" , stderr); } @@ -235,7 +268,7 @@ int main_loop(srs_t *srs, const char *domain, int port_enc, int port_dec) srsd_t *tmp; int sock; - sock = accept(srsd->fd, NULL, NULL); + sock = accept_nonblock(srsd->fd); if (sock < 0) { UNIXERR("accept"); continue; @@ -299,7 +332,6 @@ int main_loop(srs_t *srs, const char *domain, int port_enc, int port_dec) close(epollfd); error: - cleanexit = true; return exitcode; } @@ -322,12 +354,12 @@ static srs_t *srs_read_secrets(const char *sfile) int n = strlen(buf); ++lineno; - if (buf[n - 1] != '\n') { + if (n == sizeof(buf) - 1 && buf[n - 1] != '\n') { syslog(LOG_CRIT, "%s:%d: line too long", sfile, lineno); goto error; } - - srs_add_secret(srs, buf); + m_strrtrim(buf); + srs_add_secret(srs, skipspaces(buf)); } if (!lineno) { @@ -346,9 +378,13 @@ static srs_t *srs_read_secrets(const char *sfile) int main(int argc, char *argv[]) { + bool unsafe = false; int port_enc = DEFAULT_ENCODER_PORT; int port_dec = DEFAULT_DECODER_PORT; + const char *pidfile = NULL; + FILE *f = NULL; + int res; srs_t *srs; if (atexit(common_shutdown)) { @@ -357,7 +393,7 @@ int main(int argc, char *argv[]) } common_initialize(); - for (int c = 0; (c = getopt(argc, argv, "he:d:")) >= 0; ) { + for (int c = 0; (c = getopt(argc, argv, "he:d:p:u")) >= 0; ) { switch (c) { case 'e': port_enc = atoi(optarg); @@ -365,6 +401,12 @@ int main(int argc, char *argv[]) case 'd': port_dec = atoi(optarg); break; + case 'p': + pidfile = optarg; + break; + case 'u': + unsafe = true; + break; default: usage(); return EXIT_FAILURE; @@ -381,5 +423,38 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - return main_loop(srs, argv[optind], port_enc, port_dec); + if (pidfile) { + f = fopen(pidfile, "w"); + if (!f) { + syslog(LOG_CRIT, "unable to write pidfile %s", pidfile); + } + fprintf(f, "%d\n", getpid()); + fflush(f); + } + + if (!unsafe && drop_privileges(RUNAS_USER, RUNAS_GROUP) < 0) { + syslog(LOG_CRIT, "unable to drop privileges"); + return EXIT_FAILURE; + } + + if (daemon_detach() < 0) { + syslog(LOG_CRIT, "unable to fork"); + return EXIT_FAILURE; + } + + if (f) { + rewind(f); + ftruncate(fileno(f), 0); + fprintf(f, "%d\n", getpid()); + fflush(f); + } + res = main_loop(srs, argv[optind], port_enc, port_dec); + if (f) { + rewind(f); + ftruncate(fileno(f), 0); + fclose(f); + f = NULL; + } + syslog(LOG_INFO, "Stopping..."); + return res; }