diff -ru milter-greylist-3.0a2.orig/acl.c milter-greylist.maybeforged/acl.c
--- milter-greylist-3.0a2.orig/acl.c	2006-08-20 06:38:43.000000000 +0000
+++ milter-greylist.maybeforged/acl.c	2006-08-21 05:10:43.000000000 +0000
@@ -416,6 +416,23 @@
 	return;
 }
 
+void
+acl_add_may_be_forged(void)
+{
+	if (gacl.a_flags & A_MAY_BE_FORGED) {
+		fprintf (stderr,
+		    "may_be_forged specified twice in ACL line %d\n",
+		    conf_line);
+		exit(EX_DATAERR);
+	}
+	gacl.a_flags |= A_MAY_BE_FORGED;
+		
+	if (conf.c_debug || conf.c_acldebug)
+		printf("load acl may_be_forged\n");
+
+	return;
+}
+
 struct acl_entry *
 acl_register_entry_first(acl_type)	/* acllist must be write-locked */
 	acl_type_t acl_type;
@@ -500,6 +517,7 @@
 	char *hostname;
 	char *from;
 	char *queueid;
+	int may_be_forged;
 	struct acl_entry *acl;
 	char addrstr[IPADDRSTRLEN];
 	char whystr[HDRLEN];
@@ -512,6 +530,7 @@
 	hostname = priv->priv_hostname;
 	from = priv->priv_from;
 	queueid = priv->priv_queueid;
+	may_be_forged = priv->priv_may_be_forged;
 
 	ACL_RDLOCK;
 
@@ -642,6 +661,13 @@
 			}
 		}
 #endif
+		if (acl->a_flags & A_MAY_BE_FORGED) {
+			if (may_be_forged) {
+				retval |= EXF_MAY_BE_FORGED;
+			} else {
+				continue;
+			}
+		}
 		/*
 		 * We found an entry that matches, exit the evaluation
 		 * loop
@@ -751,6 +777,9 @@
 			     "recipient %s is whitelisted", rcpt);
 			ADD_REASON(whystr, tmpstr);
 		}
+		if (retval & EXF_MAY_BE_FORGED) {
+			ADD_REASON(whystr, "sender DNS name may be forged");
+		}
 		if (retval & EXF_DEFAULT) {
 			ADD_REASON(whystr, "this is the default action");
 		}
@@ -1008,6 +1037,10 @@
 		def = 0;
 	}
 #endif
+	if (acl->a_flags & A_MAY_BE_FORGED) {
+		mystrlcat(entrystr, "may_be_forged ", sizeof(entrystr));
+		def = 0;
+	}
 	if (acl->a_delay != -1) {
 		snprintf(tempstr, sizeof(tempstr), 
 		    "[delay %ld] ", (long)acl->a_delay);
diff -ru milter-greylist-3.0a2.orig/acl.h milter-greylist.maybeforged/acl.h
--- milter-greylist-3.0a2.orig/acl.h	2006-08-01 21:29:36.000000000 +0000
+++ milter-greylist.maybeforged/acl.h	2006-08-21 05:11:12.000000000 +0000
@@ -84,6 +84,7 @@
 	char *a_rcpt_re_copy;
 	regex_t *a_domain_re;
 	char *a_domain_re_copy;
+	int a_may_be_forged;
 #ifdef USE_DNSRBL
 	struct dnsrbl_entry *a_dnsrbl; 
 #endif
@@ -103,6 +104,7 @@
 
 /* a_flags */
 #define A_FLUSHADDR	1
+#define A_MAY_BE_FORGED	2
 
 extern int testmode;
 extern pthread_rwlock_t acl_lock;
@@ -116,6 +118,7 @@
 void acl_add_rcpt(char *);
 void acl_add_from_regex(char *);
 void acl_add_rcpt_regex(char *);
+void acl_add_may_be_forged(void);
 void acl_add_delay(time_t);
 void acl_add_autowhite(time_t);
 void acl_add_list(char *);
@@ -154,4 +157,5 @@
 #define EXF_DRAC	(1 << 14)
 #define EXF_DNSRBL	(1 << 15)
 #define EXF_BLACKLIST	(1 << 16)
+#define EXF_MAY_BE_FORGED (1 << 17)
 #endif /* _ACL_H_ */
diff -ru milter-greylist-3.0a2.orig/conf_lex.l milter-greylist.maybeforged/conf_lex.l
--- milter-greylist-3.0a2.orig/conf_lex.l	2006-08-01 21:29:36.000000000 +0000
+++ milter-greylist.maybeforged/conf_lex.l	2006-08-21 05:12:41.000000000 +0000
@@ -66,6 +66,7 @@
 code		[Cc][Oo][Dd][Ee]
 ecode		[Ee][Cc][Oo][Dd][Ee]
 msg		[Mm][Ss][Gg]
+may_be_forged	[Mm][Aa][Yy]_[Bb][Ee]_[Ff][Oo][Rr][Gg][Ee][Dd]
 openlist	"{"
 closelist	"}"
 nextln		"\\".*"\n"
@@ -148,6 +149,7 @@
 {drac}		{ return DRAC; }
 {nodrac}	{ return NODRAC; }
 {db}		{ return DB; }
+{may_be_forged}	{ return MAY_BE_FORGED; }
 {qstring}	{
 			strncpy(yylval.qstring, yytext, QSTRLEN);
 			yylval.qstring[QSTRLEN] = '\0';
diff -ru milter-greylist-3.0a2.orig/conf_yacc.y milter-greylist.maybeforged/conf_yacc.y
--- milter-greylist-3.0a2.orig/conf_yacc.y	2006-08-20 05:30:39.000000000 +0000
+++ milter-greylist.maybeforged/conf_yacc.y	2006-08-21 05:13:37.000000000 +0000
@@ -1,4 +1,4 @@
-%token TNUMBER ADDR IPADDR IP6ADDR CIDR FROM RCPT EMAIL PEER AUTOWHITE GREYLIST NOAUTH NOACCESSDB EXTENDEDREGEX NOSPF QUIET TESTMODE VERBOSE PIDFILE GLDUMPFILE QSTRING TDELAY SUBNETMATCH SUBNETMATCH6 SOCKET USER NODETACH REGEX REPORT NONE DELAYS NODELAYS ALL LAZYAW GLDUMPFREQ GLTIMEOUT DOMAIN DOMAINNAME SYNCADDR SYNCSRCADDR PORT ACL WHITELIST DEFAULT STAR DELAYEDREJECT DB NODRAC DRAC DUMP_NO_TIME_TRANSLATION LOGEXPIRED GLXDELAY DNSRBL LIST OPENLIST CLOSELIST BLACKLIST FLUSHADDR CODE ECODE MSG
+%token TNUMBER ADDR IPADDR IP6ADDR CIDR FROM RCPT EMAIL PEER AUTOWHITE GREYLIST NOAUTH NOACCESSDB EXTENDEDREGEX NOSPF QUIET TESTMODE VERBOSE PIDFILE GLDUMPFILE QSTRING TDELAY SUBNETMATCH SUBNETMATCH6 SOCKET USER NODETACH REGEX REPORT NONE DELAYS NODELAYS ALL LAZYAW GLDUMPFREQ GLTIMEOUT DOMAIN DOMAINNAME SYNCADDR SYNCSRCADDR PORT ACL WHITELIST DEFAULT STAR DELAYEDREJECT DB NODRAC DRAC DUMP_NO_TIME_TRANSLATION LOGEXPIRED GLXDELAY DNSRBL LIST OPENLIST CLOSELIST BLACKLIST FLUSHADDR CODE ECODE MSG MAY_BE_FORGED
 
 %{
 #include "config.h"
@@ -448,6 +448,7 @@
 	|	domainaddr_clause
 	|	domainregex_clause
 	|	netblock_clause
+	|	may_be_forged_clause
 	|	dnsrbl_clause
 	|	list_clause
 	;
@@ -555,6 +556,9 @@
 		}
 	;
 
+may_be_forged_clause:	MAY_BE_FORGED { acl_add_may_be_forged (); }
+	;
+
 dracdb:			DRAC DB QSTRING	{ 
 #ifdef USE_DRAC
 				conf.c_dracdb = 
diff -ru milter-greylist-3.0a2.orig/milter-greylist.c milter-greylist.maybeforged/milter-greylist.c
--- milter-greylist-3.0a2.orig/milter-greylist.c	2006-08-20 06:38:43.000000000 +0000
+++ milter-greylist.maybeforged/milter-greylist.c	2006-08-21 12:12:08.000000000 +0000
@@ -115,6 +115,7 @@
 	_SOCK_ADDR *addr;
 {
 	struct mlfi_priv *priv;
+	const char *client_resolve;
 
 	if ((priv = malloc(sizeof(*priv))) == NULL)
 		return SMFIS_TEMPFAIL;	
@@ -158,6 +159,11 @@
 		priv->priv_whitelist = EXF_WHITELIST | EXF_NONIP;
 	}
 
+	if ((client_resolve = smfi_getsymval(ctx, "{client_resolve}"))
+				!= NULL) {
+		priv->priv_may_be_forged = !strcmp(client_resolve, "FORGED");
+	}
+
 	return SMFIS_CONTINUE;
 }
 
@@ -325,7 +331,8 @@
 	    (priv->priv_whitelist & EXF_NONIP) ||
 	    (priv->priv_whitelist & EXF_DRAC) ||
 	    (priv->priv_whitelist & EXF_ACCESSDB) ||
-	    (priv->priv_whitelist & EXF_STARTTLS))
+	    (priv->priv_whitelist & EXF_STARTTLS) ||
+	    (priv->priv_whitelist & EXF_MAY_BE_FORGED))
 		return SMFIS_CONTINUE;
 
 #ifdef USE_DRAC
@@ -1341,6 +1348,7 @@
 	}
 
 	key.data = strncpy(ipkey, dotted_ip, sizeof(ipkey));
+	ipkey[sizeof(ipkey) - 1] = '\0';
 	key.size = strlen(ipkey);
 	rc = ddb->get(ddb, &key, &data, 0);
 	ddb->close(ddb);
diff -ru milter-greylist-3.0a2.orig/milter-greylist.h milter-greylist.maybeforged/milter-greylist.h
--- milter-greylist-3.0a2.orig/milter-greylist.h	2006-08-20 06:38:43.000000000 +0000
+++ milter-greylist.maybeforged/milter-greylist.h	2006-08-21 05:15:46.000000000 +0000
@@ -145,6 +145,7 @@
 	char *priv_code;
 	char *priv_ecode;
 	char *priv_msg;
+	int priv_may_be_forged;
 };
 
 sfsistat mlfi_connect(SMFICTX *, char *, _SOCK_ADDR *);
