Another checkcompat() Example

Last Update 1997-06-15 Here's another example for a checkcompat() function. It has a backdoor similar to check_rcpt5 i.e., it allows FROM addresses to be from the local domain, even though the client isn't local. This is required for people who connect from other places to your mailserver, without allowing these systems full relaying access to yours. The checks realized here are a bit more thorough: the user and the host must exist locally.
#define OUR_NETWORK 0x86f50000	/* change this	*/
#define OUR_NETMASK 0xffff0000	/* change this	*/

int
checkcompat(to, e)
	register ADDRESS *to;
	register ENVELOPE *e;
{
	extern unsigned long inet_addr();
	extern char *inet_ntoa();
	struct hostent *h;
	struct in_addr *p;
	struct passwd *pass;
	char *remote_user, *remote_host;
	char *tmp;
	int reject_relay, ok, i;
	
# ifdef lint
	if (to == NULL)
		to++;
# endif /* lint */

	if(tTd(49, 1))
	{
		printf("=========== Smart checkcompat()\n");
		printf("from=%s\n",e->e_from.q_paddr);
		printf("to=%s\n",to->q_paddr);
		printf("RealHostName = %s\n",RealHostName);
		printf("net addr = %s (%x)\n",
			inet_ntoa(RealHostAddr.sin.sin_addr),RealHostAddr.sin.sin_addr);
		printf("msg size = %d, rcpts = %d\n",e->e_msgsize,e->e_nrcpts);
		printf("EF_QUEUERUN flag = %d\n",bitset(EF_QUEUERUN,e->e_flags));
		printf("EF_INQUEUE flag = %d\n",bitset(EF_INQUEUE,e->e_flags));
	}

	/* allow all "return to sender" messages */
	if(bitset(EF_RESPONSE, e->e_flags)) return(EX_OK);

	/* is this a locally submitted message */
	if(RealHostAddr.sa.sa_family == 0) return(EX_OK);

	/* is the localmailer flag activated?  */
	/* If so, then the mail is to be received locally so it is ok */
	if(tTd(49, 1))
	{
		printf("===localmailer flag test\n");
		printf("localmailer flag = %d (%s)\n",
			bitnset(M_LOCALMAILER,to->q_mailer->m_flags),
			bitnset(M_LOCALMAILER,to->q_mailer->m_flags));
	}
	if(bitnset(M_LOCALMAILER,to->q_mailer->m_flags)) 
	{
		return(EX_OK);
	}

	/* is the sending host in our Domain? If so, then ok */
	if(tTd(49, 1))
	{
		printf("===realhostaddr test\n");
		printf("net addr = %s (%x)\n",
			inet_ntoa(RealHostAddr.sin.sin_addr),RealHostAddr.sin.sin_addr);
	}
	if(RealHostAddr.sa.sa_family == AF_INET &&
		(RealHostAddr.sin.sin_addr.s_addr & OUR_NETMASK) == OUR_NETWORK)
	{
		return(EX_OK);
	}
	
	/* neither the "from" nor the "to" addresses are local */
	/* did the "to" address derive from a local alias?  If so, */
	/* then we want to relay aliased/forwarded e-mail */
	if(tTd(49, 1))
	{
		printf("===alias test\n");
		printf("alias=%s\n",to->q_alias->q_paddr);
	}
	if(to->q_alias->q_paddr != NULL)
	{
		syslog(LOG_INFO, "%s: RELAY (alias): from=%s, to=%s",
			e->e_id, 
			e->e_from.q_paddr == NULL ? "<NONE>" :
			shortenstring(e->e_from.q_paddr, 83),
			to->q_paddr);
		return(EX_OK);
	}

	/* at this point we know we have a relay attempt going here */
	/* we will still allow the relay *iff* the domain matches our */
	/* allowed domain name *and* we can verify that the alleged */
	/* user/mail forger is a real user in our domain.  So split up */
	/* e->e_sender into "user" and "domain".  See if the user exists */
	/* and the domain matches our domain(s). */
	if(tTd(49, 1))
	{
		printf("===forged user/domain test\n");
		printf("sender = %s\n",e->e_sender);
	}
	/* first convert the sender address to lowercase */
	tmp = strdup(e->e_sender);
	i = 0;
	while(tmp[i] != '\0')
	{
		tmp[i] = tolower(tmp[i]);
		i++;
	}
	/* now tokenize the string: always assumes form of "user@domain" */
	reject_relay = 0;
	remote_user = strtok(tmp,"@");
	remote_host = strtok(NULL, "@");
	if(tTd(49, 1))
	{
		printf("remote user = %s, remote host = %s\n",
			remote_user,remote_host);
	}

	/* reject if the alleged user is "root" or */
	/* user not found in /etc/passwd file */
	if(strncmp(remote_user,"root",4) == 0) reject_relay = 1;
	setpwent();
	if((pass = sm_getpwnam(remote_user)) == NULL) reject_relay = 1;

	if(tTd(49, 1))
	{
		printf("after user lookup, reject_relay = %d\n",reject_relay);
	}

	/* now examine the hostname/domain portion of the sender */
	if(reject_relay == 0)
	{
    	/* pull the hostent structure of the remote host */
	    if((h = gethostbyname(remote_host)) == NULL) reject_relay = 1;
	
		/* now compare IP addresses to those of our domain */
		ok = 0;
	    for(i = 0; h->h_addr_list[i] != NULL; i++)
	    {
			p = (struct in_addr *) h->h_addr_list[i];
			/* found a match */
			if((p->s_addr & OUR_NETMASK) == OUR_NETWORK)
			{
				ok = 1;
				break;
			}
	    }
		if(ok == 0) reject_relay = 1;
		if(tTd(49, 1))
		{
			printf("after hostname check, reject_relay = %d\n",reject_relay);
		}
	}

	/* clean up our memory usage from above */
	free(tmp);

	/* if reject_relay is still zero, then accept the forgery */
	if(reject_relay == 0)
	{
		syslog(LOG_INFO, "%s: RELAY (forged: %s): from=%s, to=%s",
			e->e_id, 
			RealHostName,
			e->e_from.q_paddr == NULL ? "<NONE>" :
			shortenstring(e->e_from.q_paddr, 83),
			to->q_paddr);
		return(EX_OK);
	}
	
	/**********************************************/
	/* if we get to here, we do not want the mail */
	/**********************************************/
	if(tTd(49, 1))
	{
		printf("checkcompat() rejecting email\n");
		printf("from=%s, to=%s\n",e->e_from.q_paddr,to->q_paddr);
	}
	usrerr("553 We do not relay remote-site mail");
	/* e->e_flags |= EF_NO_BODY_RETN; */
	to->q_status = "5.7.1";
	syslog(LOG_NOTICE, "%s: RELAY (rejection: %s): from=%s, to=%s",
		e->e_id, 
		RealHostName,
		e->e_from.q_paddr == NULL ? "<NONE>" :
		shortenstring(e->e_from.q_paddr, 83),
		to->q_paddr);
	return(EX_UNAVAILABLE);
}

[(links)] [Hints] [Avoiding Spam] [New]
Claus Aßmann Please send comments to: <ca@informatik.uni-kiel.de>