/*
* readpolicy.c -- ZMailer's smtpserver's runtime address acceptance
* policy database mechanisms.
*
* By Matti Aarnio <mea@nic.funet.fi> after the model of
* Gabor Kiss's <kissg@sztaki.hu> first edition, which
* did require a router running in parallel to resolve
* each and all of the SMTP session's address processings.
* (Uhh... ... the load..)
*
*/
#include "mailer.h"
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h> /* For AF_**** */
#include <stdio.h>
#include "policy.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include "libz.h"
#include "libc.h"
static int parse_gen_policy();
static int parse_ip_policy();
/* These are subroutines for the policy compiler, these
are NOT subroutines for the SMTPSERVER to use */
/* XX:XX:XX! ASSUMPTION: 8 BITS PER CHAR! */
void mask_ip_bits(ipnum, width, maxwidth)
unsigned char *ipnum;
int width, maxwidth;
{
int i, bytewidth, bytemaxwidth;
bytemaxwidth = maxwidth >> 3; /* multiple of 8 */
bytewidth = (width + 7) >> 3;
/* All full zero bytes... */
for (i = bytewidth; i < bytemaxwidth; ++i)
ipnum[i] = 0;
/* Now the remaining byte */
i = 8 - (width & 7); /* Modulo 8 */
bytewidth = width >> 3;
if (i != 8) {
/* Not exactly multiple-of-byte-width operand to be masked */
/* For 'width=31' we get now 'bytewidth=3', and 'i=1' */
/* For 'width=25' we get now 'bytewidth=3', and 'i=7' */
ipnum[bytewidth] &= (0xFF << i);
}
}
static int parse_ip_policy(pbuf, str, wstr)
struct policy *pbuf;
char *str, *wstr;
{
char *s;
int width;
struct policy_ipv4 *ip4 = (struct policy_ipv4 *) pbuf;
#if defined(AF_INET6) && defined(INET6)
struct policy_ipv6 *ip6 = (struct policy_ipv6 *) pbuf;
#endif
if (*str == '[') {
++str;
s = strchr(str, ']');
if (!s)
return -1;
*s = 0;
if (CISTREQN(str, "IPv6.", 5))
str += 5;
if (CISTREQN(str, "IPv6:", 5))
str += 5;
return parse_ip_policy(pbuf, str, wstr);
}
if (strchr(str, ':') != NULL) { /* IPv6 */
#if defined(AF_INET6) && defined(INET6)
if (inet_pton(AF_INET6, str, ip6->ipnum) <= 0)
return -2;
width = atoi(wstr);
if (width > 128 || width < 0)
return -3;
ip6->width = width;
mask_ip_bits(ip6->ipnum, ip6->width, 128);
ip6->len = 19;
ip6->type = P_K_IPv6;
return 0;
#else
return -1;
#endif
}
if (inet_pton(AF_INET, str, ip4->ipnum) <= 0)
return -4;
width = atoi(wstr);
if (width > 32 || width < 0)
return -5;
ip4->width = width;
mask_ip_bits(ip4->ipnum, ip4->width, 32);
ip4->len = 7;
ip4->type = P_K_IPv4;
return 0;
}
static int parse_gen_policy(pbuf, str, type)
struct policy *pbuf;
char *str;
int type;
{
int len = strlen(str) + 1; /* Terminating \000 included! */
if (len > (255-2)) return -2; /* BAD BAD!! */
memcpy(pbuf->data, str, len);
pbuf->len = len + 2;
pbuf->type = type;
return 0;
}
/*
* int parsepolicykey(struct policy *pbuf, char *inpstr)
*
* Return 0, when parse is successfull
*/
int parsepolicykey(pbuf, str)
struct policy *pbuf;
char *str;
{
char *s = strchr(str, '/');
if (s != NULL) {
*s++ = 0;
return parse_ip_policy(pbuf, str, s);
}
if (strchr(str,'@') != NULL)
return parse_gen_policy(pbuf, str, P_K_USER);
if (*str == '_')
return parse_gen_policy(pbuf, str, P_K_TAG);
return parse_gen_policy(pbuf, str, P_K_DOMAIN);
}
struct _tokenpair {
char *name;
int key;
} attributes [] = {
{ "=", P_A_ALIAS },
{ "rejectnet", P_A_REJECTNET },
{ "freezenet", P_A_FREEZENET },
{ "rejectsource", P_A_REJECTSOURCE },
{ "freezesource", P_A_FREEZESOURCE },
{ "relaycustomer", P_A_RELAYCUSTOMER },
{ "relaycustnet", P_A_RELAYCUSTNET },
{ "relaytarget", P_A_RELAYTARGET },
{ "acceptifmx", P_A_ACCEPTifMX },
{ "acceptifdns", P_A_ACCEPTifDNS },
{ "senderokwithdns", P_A_SENDERokWithDNS },
{ "freeze", P_A_ACCEPTbutFREEZE },
{ "sendernorelay", P_A_SENDERNoRelay },
{ "message", P_A_MESSAGE },
{ "test-dns-rbl", P_A_TestDnsRBL },
{ "localdomain", P_A_LocalDomain },
{ "maxinsize", P_A_InboundSizeLimit },
{ "maxoutsize", P_A_OutboundSizeLimit },
{ "fulltrustnet", P_A_FullTrustNet },
{ "trustrecipients", P_A_TrustRecipients },
{ "rcpt-dns-rbl", P_A_RcptDnsRBL },
{ "test-rcpt-dns-rbl", P_A_TestRcptDnsRBL },
#ifdef HAVE_WHOSON_H
{ "trust-whoson", P_A_TrustWhosOn },
#endif
{ "filtering", P_A_Filtering },
{ "maxsameipsource", P_A_MaxSameIpSource },
{ NULL, 0 },
};
int parseattributepair(abuf, str1, str2)
struct attribute *abuf;
char *str1, *str2;
{
struct _tokenpair *ap = attributes;
int len = 2 + strlen(str2) + 1;
if (len > (255-2)) return -2;
abuf->len = len;
strcpy((char *)(abuf->data), str2);
while (ap->name != NULL) {
if (strcmp(ap->name, str1) == 0) {
abuf->attrib = ap->key;
return 0;
}
++ap;
}
return -1;
}
syntax highlighted by Code2HTML, v. 0.9.1