/* * * * Callout module for performing local network address and relay * checks for MX SMTP server. * * COPYRIGHT © 1999 MADGOAT SOFTWARE. ALL RIGHTS RESERVED. * * * 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. * */ /* !++TITLE: RAD_MX_LOCAL_NET_CHECK.C ! ! AUTHOR: Ruslan R. Laishev ! Copyright © 1999, Ruslan R. Laishev ! ! MODIFICATION HISTORY: ! ! 3-NOV-1999 RRL Initial coding. ! 23-AUG-2000 RRL Add additional checking in CHECK(). ! ! To make this module is available to the SMTP server: ! MX_LOGICALS.DAT: ! MX_SITE_LOCAL_NETWORK_CHECK\/SYSTEM/EXEC\RADIUS_DIR:RAD_MX_LOCAL_NET_CHECK.EXE ! !-- */ #include #include #include #include #include #define __NEW_STARLET 1 #include #include "radius.h" #ifdef __DECC #include #else #pragma builtins #endif char rad_stat [] = "RADIUS_CURRENT"; struct FAB sfab; struct RAB srab; static char buf [ 512 ]; static char key [ STAT_ENTRY_KEY2_SZ ]; static $DESCRIPTOR(faodsc, "!UB.!UB.!UB.!UB"); #pragma member_alignment save #pragma nomember_alignment LONGWORD static int SEMAPHORE = 0; static int INIT_FLAG = 0; #pragma member_alignment restore /* * 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 */ int INIT ( void **context ) { int status; /* ** Lock access for other threads */ __LOCK_LONG(&SEMAPHORE); /* ** Already initialized ? */ if ( INIT_FLAG ) { __UNLOCK_LONG(&SEMAPHORE); return SS$_NORMAL; } /* ** Set context to non-NULL value to ensuring tha CLEANUP routine will be called */ *context = (void *) -1; /* ** Open a RADIUS_CURREN file */ sfab = cc$rms_fab; sfab.fab$b_fac = FAB$M_GET; sfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD | FAB$M_SHRDEL; sfab.fab$l_fna = rad_stat; sfab.fab$b_fns = sizeof(rad_stat)-1; sfab.fab$l_dna = ".DAT"; sfab.fab$b_dns = 4; if ( !(1 & (status = sys$open(&sfab))) ) { __UNLOCK_LONG(&SEMAPHORE); return SS$_NORMAL; } /* ** Set a global buffering mode */ sfab.fab$w_gbc = max(64,sfab.fab$w_gbc); /* ** Initalize a RAB and connect stream */ srab = cc$rms_rab; srab.rab$l_fab = &sfab; if ( 1 & (status = sys$connect(&srab)) ) INIT_FLAG = 1; srab.rab$b_rac = RAB$C_KEY; srab.rab$v_nlk = srab.rab$v_rrl = 1; srab.rab$l_ubf = buf; srab.rab$w_usz = sizeof(buf); srab.rab$b_krf = STAT_ENTRY_KEY2_REF; srab.rab$b_ksz = STAT_ENTRY_KEY2_SZ; srab.rab$l_kbf = key; /* ** */ __UNLOCK_LONG(&SEMAPHORE); 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 ( void **context, struct in_addr *addr, int *relay_ok ) { int status; struct dsc$descriptor dsc; /* ** Set relay to disable by default */ *relay_ok = 0; /* ** Lock an access to the RAB */ __LOCK_LONG(&SEMAPHORE); /* ** The file has been not opened ? */ if ( !INIT_FLAG ) { __UNLOCK_LONG(&SEMAPHORE); return SS$_INSFARG; } /* ** Prepare key */ memset(key,' ',sizeof(key)); INIT_SDESC(dsc,sizeof(key),key); status = sys$fao(&faodsc,&dsc.dsc$w_length,&dsc, (addr->s_addr) & 0xff, (addr->s_addr >> 8) & 0xff, (addr->s_addr >> 16) & 0xff, (addr->s_addr >> 24) & 0xff); if ( !(1 & status) ) lib$signal(status); /* ** Find an given IP address */ status = sys$find(&srab); __UNLOCK_LONG(&SEMAPHORE); /* ** If the IP address is found set relay to enable */ return (*relay_ok = (1 & status)); } /* 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 */ int CLEANUP ( void **context ) { /* ** Lock access to the RAB anf FAB */ __LOCK_LONG(&SEMAPHORE); /* ** Is there something to do ? */ if ( !INIT_FLAG ) { __UNLOCK_LONG(&SEMAPHORE); return SS$_NORMAL; } /* ** Close FAB and return status */ sys$close(&sfab); INIT_FLAG = 0; __UNLOCK_LONG(&SEMAPHORE); return SS$_NORMAL; } /* CLEANUP */