/* * local_net_check.c * * * Callout module for performing local network address and relay * checks for MX SMTP server. Copyright (c) 2008, Matthew Madison. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright owner nor the names of any other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * To build this module (ALPHA): * * $ CC/DECC LOCAL_NET_CHECK * $ LINK/SHARE/EXEC=dev:[dir]LOCAL_NET_CHECK.EXE LOCAL_NET_CHECK.OBJ,SYS$INPUT:/OPT * SYMBOL_VECTOR=(INIT=PROCEDURE,CHECK=PROCEDURE,CLEANUP=PROCEDURE) * * * To build this module (VAX): * $ CC/DECC LOCAL_NET_CHECK * $ LINK/SHARE/EXEC=dev:[dir]LOCAL_NET_CHECK.EXE LOCAL_NET_CHECK.OBJ,SYS$INPUT:/OPT * UNIVERSAL=INIT,CHECK,CLEANUP * * * To make this module available to the SMTP server: * * $ DEFINE/SYSTEM/EXEC MX_SITE_LOCAL_NETWORK_CHECK dev:[dir]LOCAL_NET_CHECK * * * N.B.: The MX SMTP server uses asynchronous I/O to manage multiple incoming * connections. Be careful when performing any I/O operations in this * module, since any significant delays could cause SMTP sessions to * fail! * * N.B.: Be careful about using C run-time library routines in this module. * It is loaded by the SMTP server dynamically at run-time, and the * CRTL may not be initialized properly when these routines are called. * */ #include #include #include #include #include #include #include struct my_context { int initialized; }; static unsigned int myctxsize = sizeof(struct my_context); /* * ROUTINE NAME: INIT * * DESCRIPTION: * Initializes the context used by this module. * * If you do not need to maintain any context between calls to your * CHECK routine, it is OK to simply set the context pointer to NULL. * If you do this, your CLEANUP routine will never be called. * * PARAMETERS: * context: address of a pointer to the allocated context * * RETURNS: VMS condition value */ unsigned int INIT (struct my_context **context) { unsigned int status; status = LIB$GET_VM(&myctxsize, context); if ($VMS_STATUS_SUCCESS(status)) (*context)->initialized = 1; return status; } /* INIT */ /* * ROUTINE NAME: CHECK * * DESCRIPTION: * Checks to see if a host's network address is local (on the "inside" network) * and also indicates whether the host is permitted to use the MX SMTP server * as a relay (i.e., where both the MAIL FROM domain name and RCPT TO domain name * are non-local). * * PARAMETERS: * context: address of a pointer to the context allocated in the INIT routine * addr: address of the IP network address (in) * relay_ok: address of an int (out); set this to 1 if relay is permitted, 0 otherwise * * RETURNS: int * 1 = network address is local ("inside") * 0 = network address is remote ("outside") */ int CHECK (struct my_context **context, struct in_addr *addr, int *relay_ok) { struct in_addr okaddr, okmask; /* * Sample check for loopback network */ okaddr.s_addr = inet_addr("127.0.0.0"); okmask.s_addr = inet_addr("255.0.0.0"); /* * Never allow relay, even if the host is inside */ *relay_ok = 0; /* * The check -- apply the netmask to the address; * it is local if the result matches the loopback network number */ return ((addr->s_addr & okmask.s_addr) == okaddr.s_addr) ? 1 : 0; } /* CHECK */ /* * ROUTINE NAME: CLEANUP * * DESCRIPTION: * Cleans up the context allocated in the INIT routine. Not called * if the INIT routine set the context to NULL. * * PARAMETERS: * context: address of pointer to context * * RETURNS: VMS condition value */ unsigned int CLEANUP (struct my_context **context) { LIB$FREE_VM(&myctxsize, context); *context = 0; return SS$_NORMAL; } /* CLEANUP */