I've been work(play?)ing with postscreen for several month, and
I thought I'd like to get reverse name of client IP in the
postscreen logs too.
I guess that the postscreen must process all tests as quickly as
possible, so, time consuming functions like DNS resolv,
etc. should be asynchronous, parallel, and have appropriate
giving-ups ;-)

Attached codes do resolve reverse name of clients and attached it
to the log lines. In doing this, I did not added new service for
asynchronous resolve, instead, give dnsblog service a second job.
-- Yes, this is highly experimental.
other modifications are to use these reverse names in the logs
and make REJECT logs as seamless as smtpd's (plus, a little bit
my favor).

patch is diff to postfix-2.8-20101206.
any comments would be appreciated.

Thanks.
--
Tomo.M
diff -ru postfix-2.8-20101206.orig/src/dnsblog/dnsblog.c postfix-2.8-20101206.n2/src/dnsblog/dnsblog.c
--- postfix-2.8-20101206.orig/src/dnsblog/dnsblog.c	2010-10-09 03:01:33.000000000 +0900
+++ postfix-2.8-20101206.n2/src/dnsblog/dnsblog.c	2010-12-08 23:22:32.000000000 +0900
@@ -122,6 +122,7 @@
   */
 #define STR(x)			vstring_str(x)
 #define LEN(x)			VSTRING_LEN(x)
+#define STREQ(x,y)		(strcmp((x),(y)) == 0)

 /* static void dnsblog_query - query DNSBL for client address */

@@ -208,6 +209,48 @@
     return (result);
 }

+/* static VSTRING * revname_query - query Reverse Name for client address */
+
+#define  CLIENT_NAME_UNKNOWN  "unknown"
+#define  AIRFORCE_MARK  "=*="
+
+static VSTRING *revname_query(VSTRING *result, const char *addr)
+{
+    const char *myname = "revname_query";
+    MAI_HOSTNAME_STR client_name;
+    struct sockaddr_storage ss;
+    struct sockaddr *sa;
+    SOCKADDR_SIZE sa_length;
+    struct addrinfo *res0;
+
+    if (msg_verbose)
+	msg_info("%s: reverse resolve addr %s", myname, addr);
+
+    sa = (struct sockaddr *) & ss;
+
+    if (hostaddr_to_sockaddr(addr, (char *) 0, 0, &res0) != 0)
+      msg_fatal("%s: unable to convert address %s", myname, addr);
+    sa_length = res0->ai_addrlen;
+    if(sa_length > sizeof(ss))
+      sa_length = sizeof(ss);
+    memcpy((char *) sa, res0->ai_addr, sa_length);
+    freeaddrinfo(res0);
+
+    VSTRING_RESET(result);
+    if (sockaddr_to_hostname(sa, sa_length, &client_name,
+			     (MAI_SERVNAME_STR *) 0, 0) != 0) {
+      vstring_strcat(result, CLIENT_NAME_UNKNOWN);
+    } else {
+      vstring_strcat(result, client_name.buf);
+	/* stop here so far.
+	 * may add further reverse_name validation.
+	 */
+    }
+
+    VSTRING_TERMINATE(result);
+    return (result);
+}
+
 /* dnsblog_service - perform service for client */

 static void dnsblog_service(VSTREAM *client_stream, char *unused_service,
@@ -230,7 +273,10 @@
 		  ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, rbl_domain,
 		  ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, addr,
 		  ATTR_TYPE_END) == 2) {
-	(void) dnsblog_query(result, STR(rbl_domain), STR(addr));
+        if (STREQ(STR(rbl_domain), AIRFORCE_MARK))
+	    (void) revname_query(result, STR(addr));
+        else
+	    (void) dnsblog_query(result, STR(rbl_domain), STR(addr));
 	if (var_dnsblog_delay > 0)
 	    sleep(var_dnsblog_delay);
 	attr_print(client_stream, ATTR_FLAG_NONE,
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen.c postfix-2.8-20101206.n2/src/postscreen/postscreen.c
--- postfix-2.8-20101206.orig/src/postscreen/postscreen.c	2010-12-06 09:50:12.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen.c	2010-12-08 23:22:32.000000000 +0900
@@ -533,6 +533,12 @@
     }

     /*
+     *  request resolve client's reverse name.
+     *   XXXX: when to submit request
+     */
+    ps_revname_request(state->smtp_client_addr, (char *) state);
+
+    /*
      * Reply with 421 when we can't forward more connections.
      */
     if (var_ps_post_queue_limit > 0
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen.h postfix-2.8-20101206.n2/src/postscreen/postscreen.h
--- postfix-2.8-20101206.orig/src/postscreen/postscreen.h	2010-12-06 08:37:33.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen.h	2010-12-08 23:22:32.000000000 +0900
@@ -64,6 +64,8 @@
     char   *sender;			/* MAIL FROM */
     VSTRING *cmd_buffer;		/* command read buffer */
     int     read_state;			/* command read state machine */
+    int     resolver;			/* DNS resolver file descriptor (dnsblog) */
+    char   *reverse_name;		/* reverse name of client(not checked)*/
 } PS_STATE;

 #define PS_TIME_STAMP_NEW		(0)	/* test was never passed */
@@ -317,6 +319,7 @@
   */
 #define STR(x)  vstring_str(x)
 #define LEN(x)  VSTRING_LEN(x)
+#define STREQ(x,y)	(strcmp((x),(y)) == 0)

  /*
   * postscreen_state.c
@@ -324,6 +327,14 @@
 #define PS_CLIENT_ADDR_PORT(state) \
 	(state)->smtp_client_addr, (state)->smtp_client_port

+#define PS_CLIENT_NAME_ADDR(state) \
+	((state)->reverse_name ? (state)->reverse_name : "unknown"), \
+	(state)->smtp_client_addr
+
+#define PS_CLIENT_NAME_ADDR_PORT(state) \
+	((state)->reverse_name ? (state)->reverse_name : "unknown"), \
+	(state)->smtp_client_addr, (state)->smtp_client_port
+
 #define PS_PASS_SESSION_STATE(state, what, bits) do { \
 	if (msg_verbose) \
 	    msg_info("PASS %s [%s]:%s", (what), PS_CLIENT_ADDR_PORT(state)); \
@@ -388,6 +399,8 @@
 extern void ps_dnsbl_init(void);
 extern int ps_dnsbl_retrieve(const char *, const char **, int);
 extern int ps_dnsbl_request(const char *, void (*) (int, char *), char *);
+extern void ps_revname_receive(int, char *);
+extern int ps_revname_request(const char *, char *);

  /*
   * postscreen_tests.c
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen_dnsbl.c postfix-2.8-20101206.n2/src/postscreen/postscreen_dnsbl.c
--- postfix-2.8-20101206.orig/src/postscreen/postscreen_dnsbl.c	2010-11-28 06:35:17.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen_dnsbl.c	2010-12-08 23:22:32.000000000 +0900
@@ -199,6 +199,10 @@
 static VSTRING *reply_dnsbl;		/* domain in DNSBLOG reply */
 static VSTRING *reply_addr;		/* adress list in DNSBLOG reply */

+static VSTRING *reply_client_addr;	/* client address in DNSBLOG reply */
+static VSTRING *reply_dummy;		/* dummy domain in DNSBLOG reply */
+static VSTRING *reply_reverse_name;	/* reverse name in DNSBLOG reply */
+
 /* ps_dnsbl_add_site - add DNSBL site information */

 static void ps_dnsbl_add_site(const char *site)
@@ -536,4 +540,70 @@
     reply_client = vstring_alloc(100);
     reply_dnsbl = vstring_alloc(100);
     reply_addr = vstring_alloc(100);
+
+    reply_client_addr = vstring_alloc(100);
+    reply_dummy = vstring_alloc(100);
+    reply_reverse_name = vstring_alloc(100);
+}
+
+/* ps_revname_receive  - receive reply Reverse Name of client */
+void	ps_revname_receive(int event, char *context)
+{
+    const char *myname = "ps_revname_receive";
+    PS_STATE *state = (PS_STATE *)context;
+    VSTREAM *stream;
+
+    if (state->resolver < 0)
+      return;
+
+    PS_CLEAR_EVENT_REQUEST(state->resolver, ps_revname_receive, context);
+
+    stream = vstream_fdopen(state->resolver, O_RDWR);
+    if (attr_scan(stream,
+		  ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
+		  ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, reply_dummy,
+		  ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, reply_client_addr,
+		  ATTR_TYPE_STR, MAIL_ATTR_RBL_ADDR, reply_reverse_name,
+		  ATTR_TYPE_END) == 3
+	&& STREQ(STR(reply_client_addr), state->smtp_client_addr)
+	&& LEN(reply_reverse_name) > 0) {
+
+      state->reverse_name = mystrdup(STR(reply_reverse_name));
+    } else {
+      /* XXX */
+      state->reverse_name = mystrdup("unknown");
+    }
+    vstream_fclose(stream);
+    state->resolver = -1;
+}
+
+/* ps_revname_request  - request Reverse Name of client */
+#define   AIRFORCE_MARK  "=*="
+
+int	ps_revname_request(const char *client_addr, char *state)
+{
+    const char *myname = "ps_revname_request";
+    int	  fd;
+    PS_STATE * ctx = (PS_STATE *) state;
+    VSTREAM *stream;
+
+    if ((fd = LOCAL_CONNECT("private/" DNSBL_SERVICE, NON_BLOCKING, 1)) < 0) {
+      msg_warn("%s: connect to " DNSBL_SERVICE " service: %m", myname);
+      ctx->resolver = -1;
+      return(-1);
+    }
+    ctx->resolver = fd;
+    stream = vstream_fdopen(fd, O_RDWR);
+    attr_print(stream, ATTR_FLAG_NONE,
+	       ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, AIRFORCE_MARK,
+	       ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, client_addr,
+	       ATTR_TYPE_END);
+    if (vstream_fflush(stream) != 0) {
+      msg_warn("%s: error sending to " DNSBL_SERVICE " service: %m", myname);
+      vstream_fclose(stream);
+      ctx->resolver = -1;
+      return(-1);
+    }
+    PS_READ_EVENT_REQUEST(fd, ps_revname_receive, state, DNSBLOG_TIMEOUT);
+    return(0);
 }
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen_early.c postfix-2.8-20101206.n2/src/postscreen/postscreen_early.c
--- postfix-2.8-20101206.orig/src/postscreen/postscreen_early.c	2010-12-06 07:49:28.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen_early.c	2010-12-08 23:22:32.000000000 +0900
@@ -106,7 +106,7 @@
 	 * client to a dummy protocol engine, or continue to the next test.
 	 */
 #define PS_DNSBL_FORMAT \
-	"%s 5.7.1 Service unavailable; client [%s] blocked using %s\r\n"
+	"%s 4.7.1 <%s[%s]>: Client host rejected: %s\r\n"

 	if (state->flags & PS_STATE_FLAG_DNSBL_TODO) {
 	    dnsbl_score =
@@ -123,14 +123,14 @@
 		switch (ps_dnsbl_action) {
 		case PS_ACT_DROP:
 		    state->dnsbl_reply = vstring_sprintf(vstring_alloc(100),
-						     PS_DNSBL_FORMAT, "521",
-				       state->smtp_client_addr, dnsbl_name);
+						     PS_DNSBL_FORMAT, "421",
+				       PS_CLIENT_NAME_ADDR(state), dnsbl_name);
 		    PS_DROP_SESSION_STATE(state, STR(state->dnsbl_reply));
 		    return;
 		case PS_ACT_ENFORCE:
 		    state->dnsbl_reply = vstring_sprintf(vstring_alloc(100),
-						     PS_DNSBL_FORMAT, "550",
-				       state->smtp_client_addr, dnsbl_name);
+						     PS_DNSBL_FORMAT, "450",
+				       PS_CLIENT_NAME_ADDR(state), dnsbl_name);
 		    PS_ENFORCE_SESSION_STATE(state, STR(state->dnsbl_reply));
 		    break;
 		case PS_ACT_IGNORE:
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen_misc.c postfix-2.8-20101206.n2/src/postscreen/postscreen_misc.c
--- postfix-2.8-20101206.orig/src/postscreen/postscreen_misc.c	2010-12-06 07:50:09.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen_misc.c	2010-12-08 23:22:32.000000000 +0900
@@ -108,6 +108,13 @@
 		 "OLD" : "NEW", PS_CLIENT_ADDR_PORT(state));

     /*
+     * clear reverse dns resolve request
+     */
+    if (state->resolver >= 0) {
+	ps_revname_receive(EVENT_TIME, (char *) state);
+    }
+
+    /*
      * Update the postscreen cache. This still supports a scenario where a
      * client gets whitelisted in the course of multiple sessions, as long as
      * that client does not "fail" any test.
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen_smtpd.c postfix-2.8-20101206.n2/src/postscreen/postscreen_smtpd.c
--- postfix-2.8-20101206.orig/src/postscreen/postscreen_smtpd.c	2010-12-01 07:42:19.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen_smtpd.c	2010-12-08 23:22:32.000000000 +0900
@@ -321,9 +321,9 @@
     if ((addr = ps_extract_addr(ps_temp, colon + 1)) == 0)
 	return (PS_SEND_REPLY(state,
 			      "501 5.1.3 Bad recipient address syntax\r\n"));
-    msg_info("NOQUEUE: reject: RCPT from [%s]:%s: %.*s; "
-	     "from=<%s>, to=<%s>, proto=%s, helo=<%s>",
-	     PS_CLIENT_ADDR_PORT(state),
+    msg_info("NOQUEUE: reject: RCPT from %s[%s]: %.*s; "
+	     "from=<%s> to=<%s> proto=%s helo=<%s>",
+	     PS_CLIENT_NAME_ADDR(state),
 	     (int) strlen(state->rcpt_reply) - 2, state->rcpt_reply,
 	     state->sender, addr, state->protocol,
 	     state->helo_name ? state->helo_name : "");
@@ -812,6 +812,11 @@
     static char *myname = "ps_smtpd_tests";

     /*
+     *
+     */
+    msg_info("CLIENT %s[%s]:%s", PS_CLIENT_NAME_ADDR_PORT(state));
+
+    /*
      * Report errors and progress in the context of this test.
      */
     PS_BEGIN_TESTS(state, "tests after SMTP handshake");
diff -ru postfix-2.8-20101206.orig/src/postscreen/postscreen_state.c postfix-2.8-20101206.n2/src/postscreen/postscreen_state.c
--- postfix-2.8-20101206.orig/src/postscreen/postscreen_state.c	2010-12-01 06:40:55.000000000 +0900
+++ postfix-2.8-20101206.n2/src/postscreen/postscreen_state.c	2010-12-08 23:22:32.000000000 +0900
@@ -163,6 +163,8 @@
     state->sender = 0;
     state->cmd_buffer = 0;
     state->read_state = 0;
+    state->resolver = (-1);
+    state->reverse_name = 0;

     /*
      * Update the stress level.
@@ -219,6 +221,8 @@
 	myfree(state->sender);
     if (state->cmd_buffer)
 	vstring_free(state->cmd_buffer);
+    if (state->reverse_name)
+	myfree(state->reverse_name);
     myfree((char *) state);

     if (ps_check_queue_length < 0 || ps_post_queue_length < 0)

Attachment: pgpUG81oGBMPL.pgp
Description: PGP signature

Reply via email to