2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 06:05:37 +00:00

snapshot-20000823

This commit is contained in:
Wietse Venema
2000-08-23 00:00:00 +00:00
parent df4c6b1b13
commit 77741d9964
10 changed files with 473 additions and 9 deletions

View File

@@ -4147,3 +4147,12 @@ Apologies for any names omitted.
that cannot be represented with the off_t type that is used
by standard functions such as lseek(2). Problem reported
by Blaz Zupan @ amis.net.
20000823
Feature: all this discussion about when to reject mail and
when not made me decide to implement a TCP-based map type
so that it becomes relatively simple to implement dynamic
access controls, for example, hold off mail from an unknown
client or sender until we have completed some investigation,
after which we will either reject or accept.

View File

@@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20000822"
#define DEF_MAIL_VERSION "Snapshot-20000823"
extern char *var_mail_version;
/* LICENSE

View File

@@ -32,6 +32,7 @@
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_RULE
-TDICT_TCP
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@@ -21,7 +21,8 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
@@ -44,7 +45,8 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
sane_link.o unescape.o timed_read.o timed_write.o
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
hex_quote.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
@@ -59,7 +61,7 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \
watchdog.h spawn_command.h sane_fsops.h
watchdog.h spawn_command.h sane_fsops.h dict_tcp.h hex_quote.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
@@ -75,7 +77,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
mystrtok sigdelay translit valid_hostname vstream_popen \
vstring vstring_vstream doze select_bug stream_test mac_expand \
watchdog unescape
watchdog unescape hex_quote
LIB_DIR = ../lib
INC_DIR = ../include
@@ -249,6 +251,11 @@ unescape: $(LIB)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
hex_quote: $(LIB)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -260,7 +267,8 @@ depend: $(MAKES)
stream_test: stream_test.c $(LIB)
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
tests: valid_hostname_test mac_expand_test dict_test unescape_test
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
hex_quote_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
@@ -277,6 +285,12 @@ unescape_test: unescape unescape.in unescape.ref
diff -b unescape.ref unescape.tmp
rm -f unescape.tmp
hex_quote_test: hex_quote
./hex_quote <hex_quote.c | od -cb >hex_quote.tmp
od -cb <hex_quote.c >hex_quote.ref
cmp hex_quote.ref hex_quote.tmp
rm -f hex_quote.ref hex_quote.tmp
DB_TYPE = `../postconf/postconf -h default_database_type`
dict_test: dict_open testdb dict_test.in dict_test.ref
@@ -416,6 +430,7 @@ dict_open.o: vstream.h
dict_open.o: vbuf.h
dict_open.o: dict_env.h
dict_open.o: dict_unix.h
dict_open.o: dict_tcp.h
dict_open.o: dict_dbm.h
dict_open.o: dict_db.h
dict_open.o: dict_nis.h
@@ -445,6 +460,20 @@ dict_regexp.o: dict.h
dict_regexp.o: argv.h
dict_regexp.o: dict_regexp.h
dict_regexp.o: mac_parse.h
dict_tcp.o: dict_tcp.c
dict_tcp.o: sys_defs.h
dict_tcp.o: msg.h
dict_tcp.o: mymalloc.h
dict_tcp.o: vstring.h
dict_tcp.o: vbuf.h
dict_tcp.o: vstream.h
dict_tcp.o: vstring_vstream.h
dict_tcp.o: connect.h
dict_tcp.o: iostuff.h
dict_tcp.o: hex_quote.h
dict_tcp.o: dict.h
dict_tcp.o: argv.h
dict_tcp.o: dict_tcp.h
dict_unix.o: dict_unix.c
dict_unix.o: sys_defs.h
dict_unix.o: msg.h
@@ -465,6 +494,7 @@ doze.o: doze.c
doze.o: sys_defs.h
doze.o: msg.h
doze.o: iostuff.h
dup2_pass_on_exec.o: dup2_pass_on_exec.c
duplex_pipe.o: duplex_pipe.c
duplex_pipe.o: sys_defs.h
duplex_pipe.o: iostuff.h
@@ -526,6 +556,12 @@ get_hostname.o: mymalloc.h
get_hostname.o: msg.h
get_hostname.o: valid_hostname.h
get_hostname.o: get_hostname.h
hex_quote.o: hex_quote.c
hex_quote.o: sys_defs.h
hex_quote.o: msg.h
hex_quote.o: vstring.h
hex_quote.o: vbuf.h
hex_quote.o: hex_quote.h
htable.o: htable.c
htable.o: sys_defs.h
htable.o: mymalloc.h
@@ -948,6 +984,7 @@ vstring_vstream.o: vstream.h
vstring_vstream.o: vstring_vstream.h
watchdog.o: watchdog.c
watchdog.o: sys_defs.h
watchdog.o: posix_signals.h
watchdog.o: msg.h
watchdog.o: mymalloc.h
watchdog.o: watchdog.h

View File

@@ -156,6 +156,7 @@
#include <dict.h>
#include <dict_env.h>
#include <dict_unix.h>
#include <dict_tcp.h>
#include <dict_dbm.h>
#include <dict_db.h>
#include <dict_nis.h>
@@ -180,6 +181,7 @@ typedef struct {
static DICT_OPEN_INFO dict_open_info[] = {
"environ", dict_env_open,
"unix", dict_unix_open,
"tcp", dict_tcp_open,
#ifdef HAS_DBM
"dbm", dict_dbm_open,
#endif
@@ -318,6 +320,7 @@ ARGV *dict_mapnames()
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
/* Utility library. */
@@ -343,6 +346,8 @@ main(int argc, char **argv)
const char *value;
int ch;
signal(SIGPIPE, SIG_IGN);
msg_vstream_init(argv[0], VSTREAM_ERR);
while ((ch = GETOPT(argc, argv, "v")) > 0) {
switch (ch) {
@@ -380,7 +385,9 @@ main(int argc, char **argv)
vstream_printf("%s: deleted\n", key);
} else if (strcmp(cmd, "get") == 0 && key && !value) {
if ((value = dict_get(dict, key)) == 0) {
vstream_printf("%s: not found\n", key);
vstream_printf("%s: %s\n", key,
dict_errno == DICT_ERR_RETRY ?
"soft error" : "not found");
} else {
vstream_printf("%s=%s\n", key, value);
}
@@ -388,7 +395,7 @@ main(int argc, char **argv)
dict_put(dict, key, value);
vstream_printf("%s=%s\n", key, value);
} else {
vstream_printf("usage: del key|get key|put key=value");
vstream_printf("usage: del key|get key|put key=value\n");
}
vstream_fflush(VSTREAM_OUT);
}

191
postfix/util/dict_tcp.c Normal file
View File

@@ -0,0 +1,191 @@
/*++
/* NAME
/* dict_tcp 3
/* SUMMARY
/* dictionary manager interface to tcp-based lookup tables
/* SYNOPSIS
/* #include <dict_tcp.h>
/*
/* DICT *dict_tcp_open(map, dummy, dict_flags)
/* const char *map;
/* int dummy;
/* int dict_flags;
/* DESCRIPTION
/* dict_tcp_open() makes a TCP server accessible via the generic
/* dictionary operations described in dict_open(3).
/* The \fIdummy\fR argument is not used. Server access is read-only
/* (i.e., only lookups are implemented).
/*
/* Map names have the form host:port.
/*
/* The map implements a very simple protocol: the query is sent as
/* one line of text, and the reply is sent back in the same format.
/* Data is sent as a newline-terminated string. % and non-printable
/* characters are replaced by %xx, xx being the corresponding
/* hexadecimal value.
/* SEE ALSO
/* dict(3) generic dictionary manager
/* DIAGNOSTICS
/* Fatal errors: out of memory, unknown host or service name,
/* attempt to update map.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include "sys_defs.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
/* Utility library. */
#include "msg.h"
#include "mymalloc.h"
#include "vstring.h"
#include "vstream.h"
#include "vstring_vstream.h"
#include "connect.h"
#include "hex_quote.h"
#include "dict.h"
#include "dict_tcp.h"
/* Application-specific. */
typedef struct {
DICT dict; /* generic members */
char *map; /* server host:port */
VSTRING *raw_buf; /* raw buffer */
VSTRING *hex_buf; /* hexified buffer */
VSTREAM *fp; /* I/O stream */
} DICT_TCP;
#define DICT_TCP_MAXTRY 10
#define DICT_TCP_TMOUT 100
#define STR(x) vstring_str(x)
/* dict_tcp_lookup - query TCP server */
static const char *dict_tcp_lookup(DICT *dict, const char *key)
{
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
int fd;
int i;
dict_errno = 0;
for (i = 0; /* see below */ ; i++) {
/*
* Try to connect a few times before giving up.
*/
if (i >= DICT_TCP_MAXTRY) {
dict_errno = DICT_ERR_RETRY;
return (0);
}
/*
* Sleep between connection attempts.
*/
if (i > 0)
sleep(1);
/*
* Try to connect to the server.
*/
if (dict_tcp->fp == 0) {
if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
msg_warn("connect to TCP map %s: %m", dict_tcp->map);
continue;
}
dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
vstream_control(dict_tcp->fp,
VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
VSTREAM_CTL_END);
}
/*
* Allocate per-map buffers on the fly.
*/
if (dict_tcp->raw_buf == 0) {
dict_tcp->raw_buf = vstring_alloc(10);
dict_tcp->hex_buf = vstring_alloc(10);
}
/*
* Send query and receive response. Both are %XX quoted and both are
* terminated by newline.
*/
hex_quote(dict_tcp->hex_buf, key);
vstream_fprintf(dict_tcp->fp, "%s\n", STR(dict_tcp->hex_buf));
errno = 0;
if (vstring_get_nonl(dict_tcp->hex_buf, dict_tcp->fp) == VSTREAM_EOF) {
msg_warn("read TCP map reply from %s: %m", dict_tcp->map);
} else if (!hex_unquote(dict_tcp->raw_buf, STR(dict_tcp->hex_buf))) {
msg_warn("read TCP map reply from %s: malformed reply %.100s",
dict_tcp->map, STR(dict_tcp->hex_buf));
} else {
return (STR(dict_tcp->raw_buf));
}
/*
* That did not work. Clean up and try again.
*/
(void) vstream_fclose(dict_tcp->fp);
dict_tcp->fp = 0;
}
}
/* dict_tcp_update - add or update table entry */
static void dict_tcp_update(DICT *dict, const char *unused_name, const char *unused_value)
{
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
msg_fatal("dict_tcp_update: attempt to update map %s", dict_tcp->map);
}
/* dict_tcp_close - close TCP map */
static void dict_tcp_close(DICT *dict)
{
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
if (dict_tcp->fp)
(void) vstream_fclose(dict_tcp->fp);
if (dict_tcp->raw_buf)
vstring_free(dict_tcp->raw_buf);
if (dict_tcp->hex_buf)
vstring_free(dict_tcp->hex_buf);
myfree(dict_tcp->map);
myfree((char *) dict_tcp);
}
/* dict_tcp_open - open TCP map */
DICT *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
{
DICT_TCP *dict_tcp;
dict_errno = 0;
dict_tcp = (DICT_TCP *) mymalloc(sizeof(*dict_tcp));
dict_tcp->fp = 0;
dict_tcp->raw_buf = dict_tcp->hex_buf = 0;
dict_tcp->dict.lookup = dict_tcp_lookup;
dict_tcp->dict.update = dict_tcp_update;
dict_tcp->dict.close = dict_tcp_close;
dict_tcp->dict.fd = -1;
dict_tcp->map = mystrdup(map);
dict_tcp->dict.flags = dict_flags | DICT_FLAG_FIXED;
return (&dict_tcp->dict);
}

35
postfix/util/dict_tcp.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef _DICT_TCP_H_INCLUDED_
#define _DICT_TCP_H_INCLUDED_
/*++
/* NAME
/* dict_tcp 3h
/* SUMMARY
/* dictionary manager interface to tcp-based lookup tables
/* SYNOPSIS
/* #include <dict_tcp.h>
/* DESCRIPTION
/* .nf
/*
* Utility library.
*/
#include <dict.h>
/*
* External interface.
*/
extern DICT *dict_tcp_open(const char *, int, int);
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
#endif

148
postfix/util/hex_quote.c Normal file
View File

@@ -0,0 +1,148 @@
/*++
/* NAME
/* hex_quote 3
/* SUMMARY
/* quote/unquote text, HTTP style.
/* SYNOPSIS
/* #include <hex_quote.h>
/*
/* VSTRING *hex_quote(hex, raw)
/* VSTRING *hex;
/* const char *raw;
/*
/* VSTRING *hex_unquote(raw, hex)
/* VSTRING *raw;
/* const char *hex;
/* DESCRIPTION
/* hex_quote() takes a null-terminated string and replaces non-printable
/* characters and % by %XX, XX being the two-digit hexadecimal equivalent.
/* The hexadecimal codes are produced as upper-case characters. The result
/* value is the hex argument.
/*
/* hex_unquote() performs the opposite transformation. This function
/* understands lowercase and uppercase %XX sequences. The result
/* value is the raw argument in case of success, a null pointer otherwise.
/* BUGS
/* Cannot process null characters.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include "sys_defs.h"
#include <ctype.h>
/* Utility library. */
#include "msg.h"
#include "vstring.h"
#include "hex_quote.h"
/* Application-specific. */
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
/* hex_quote - raw data to quoted */
VSTRING *hex_quote(VSTRING *hex, const char *raw)
{
const char *cp;
int ch;
VSTRING_RESET(hex);
for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
if (ch != '%' && ISPRINT(ch)) {
VSTRING_ADDCH(hex, ch);
} else {
vstring_sprintf_append(hex, "%%%02X", ch);
}
}
VSTRING_TERMINATE(hex);
return (hex);
}
/* hex_unquote - quoted data to raw */
VSTRING *hex_unquote(VSTRING *raw, const char *hex)
{
const char *cp;
int ch;
VSTRING_RESET(raw);
for (cp = hex; (ch = *cp) != 0; cp++) {
if (ch == '%') {
if (ISDIGIT(cp[1]))
ch = (cp[1] - '0') << 4;
else if (cp[1] >= 'a' && cp[1] <= 'f')
ch = (cp[1] - 'a' + 10) << 4;
else if (cp[1] >= 'A' && cp[1] <= 'F')
ch = (cp[1] - 'A' + 10) << 4;
else
return (0);
if (ISDIGIT(cp[2]))
ch |= (cp[2] - '0');
else if (cp[2] >= 'a' && cp[2] <= 'f')
ch |= (cp[2] - 'a' + 10);
else if (cp[2] >= 'A' && cp[2] <= 'F')
ch |= (cp[2] - 'A' + 10);
else
return (0);
cp += 2;
}
VSTRING_ADDCH(raw, ch);
}
VSTRING_TERMINATE(raw);
return (raw);
}
#ifdef TEST
/*
* Proof-of-concept test program: convert to hex and back.
*/
#include <vstream.h>
#define BUFLEN 1024
static int read_buf(VSTREAM *fp, VSTRING *buf)
{
int len;
VSTRING_RESET(buf);
len = vstream_fread(fp, STR(buf), vstring_avail(buf));
VSTRING_AT_OFFSET(buf, len); /* XXX */
VSTRING_TERMINATE(buf);
return (len);
}
main(int unused_argc, char **unused_argv)
{
VSTRING *raw = vstring_alloc(BUFLEN);
VSTRING *hex = vstring_alloc(100);
int len;
while ((len = read_buf(VSTREAM_IN, raw)) > 0) {
hex_quote(hex, STR(raw));
if (hex_unquote(raw, STR(hex)) == 0)
msg_fatal("bad input: %.100s", STR(hex));
if (LEN(raw) != len)
msg_fatal("len %d != raw len %d", len, LEN(raw));
if (vstream_fwrite(VSTREAM_OUT, STR(raw), LEN(raw)) != LEN(raw))
msg_fatal("write error: %m");
}
vstream_fflush(VSTREAM_OUT);
vstring_free(raw);
vstring_free(hex);
return (0);
}
#endif

36
postfix/util/hex_quote.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef _HEX_QUOTE_H_INCLUDED_
#define _HEX_QUOTE_H_INCLUDED_
/*++
/* NAME
/* hex_quote 3h
/* SUMMARY
/* quote/unquote text, HTTP style.
/* SYNOPSIS
/* #include <hex_quote.h>
/* DESCRIPTION
/* .nf
/*
* Utility library.
*/
#include <vstring.h>
/*
* External interface.
*/
extern VSTRING *hex_quote(VSTRING *, const char *);
extern VSTRING *hex_unquote(VSTRING *, const char *);
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
#endif

View File

@@ -825,7 +825,7 @@ typedef int pid_t;
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 7
#define PRINTFLIKE(x,y) __attribute__ ((format (printf, (x), (y))))
#else
#define PRINTFLIKE
#define PRINTFLIKE(x,y)
#endif
#endif