#define RADIUS_VMS_VERSION "RADIUS-VMS 5.0A" #pragma module RADIUS_VMS RADIUS_VMS_VERSION #define module "RAD_MAIN" /* **++ ** FACILITY: RADIUS-VMS ** ** MODULE DESCRIPTION: ** ** This is a main RADIUS-VMS module, performs an initalization task ** reading of configuration file and logocals, start all threads, ** performs control action. ** ** AUTHORS: ** ** Ruslan R. Laishev ** Copyright © 1999-2011, Ruslan R. Laishev ** ** CREATION DATE: 16-SEP-1999 ** ** MODIFICATION HISTORY: ** ** 4-OCT-1999 RRL Version 2.0.31 which performs a session limit ** check per client basis. ** 2-NOV-1999 RRL Version 2.0.32, added aditional key for ** using with conjuction with MX for real-time ** relay allowed checking for roaming users. ** 6-DEC-1999 RRL Version 2.0.33 - internal release, added login time timestamp ** in the RADIUS_CURRENT file. ** 6-DEC-1999 RRL Version 2.0.34 ** 6-DEC-1999 RRL Add RADIUS_OPCOMLVL logical name, which control ** a severity level of message sending to OPCOM ** 20-DEC-1999 RRL Add multiHOME support. ** 19-JAN-2000 RRL Fixed problem with threads cancelation. ** 24-JAN-2000 RRL Version 2.0.35 ** 1-FEB-2000 RRL Version 2.0.36 ** 11-FEB-2000 RRL Add external AAA callouts support. ** 21-MAR-2000 RRL Add RADIUS_SESSIONTMO. ** 21-FEB-2000 RRL Version 2.0.37 ** 27-FEB-2000 RRL Version 2.10 (VSA support) ** 5-APR-2000 RRL Version 2.11 (RADCP) ** 7-APR-2000 RRL Move RADCP to RAD_CP.C ** 24-APR-2000 RRL Version 2.12 ** 17-MAY-2000 RRL Version 2.13 ** 15-JUN-2000 RRL Version 2.14 ** 18-JUN-2000 RRL Fix for using TCPIP$INET_HOSTADDR ** 15-JUN-2000 RRL Version 2.15, SYSUAF password change ** 5-AUG-2000 RRL Increased a thread stack size. ** 5-AUG-2000 RRL Version 2.16 ** 12-AUG-2000 RRL Version 2.17, maintenace update. ** 27-AUG-2000 RRL Version 2.3, NT Domain authentication. ** 6-SEP-2000 RRL /FLAG=PWD_EXPIRED ** 18-SEP-2000 RRL Version 2.31,/FLAG=PWD_EXPIRED. ** 21-SEP-2000 RRL Version 2.32,maintenace update. ** 30-SEP-2000 RRL Version 2.33,no case sensivity wild cards comparing, ** global buffering option for RADIUS_USERS. ** 2-NOV-2000 RRL Version 2.34,RADIUS_ALLOW_RECTRICTED ** 10-NOV-2000 RRL Version 2.35 ** 23-NOV-2000 RRL Version 2.36, realm checking in the RADIUS_CURRENT file. ** 6-JAN-2001 RRL Version 2.4 - USR VSA support. ** 16-JAN-2001 RRL Fixed a problem with SS$_DUPLNAME. ** 18-FEB-2001 RRL Version 2.4, release. ** 19-MAR-2001 RRL Version 2.4A, cosmetic changes for an external accounting. ** 30-MAR-2001 RRL Version 2.4B, disable file I/O operations if RADIUS_ACCCOUNTING ** file cannot be oppened. ** 11-APR-2001 RRL Version 2.4C, fixed bug in the put_attribute() and incorrect truncation of the ** AVP list in reply. ** 4-AUG-2001 RRL Added a specfic handling of an USR VSA to provide a speed of ** connection authorization and accounting. ** 28-DEC-2001 RRL Some fixes in the RAD_ACCT.C ** 11-JAN-2002 RRL Some fixes in the RAD_UTIL.C ** 18-JAN-2002 RRL Version 2.5A, added Ascend IP-filters support. ** 28-FEB-2002 RRL Version 2.5B, all configuration logicals must be defined with ** /SYSTEM/EXEC. ** 20-MAR-2002 RRL Added an additional checking of used buffers. ** 5-JUN-2002 RRL Some optimization:update last-login date after accept is sent. ** 11-JUN-2002 RRL Some other optimization. ** 9-AUG-2002 RRL Added backup host for realms support. ** 2-SEP-2002 RRL Version 2.6A, Added IMSI realms support. ** 13-NOV-2002 RRL Version 2.6B, fixed problem with threads exit, it cause ** a hunging server in HIB state. ** 20-JAN-2003 RRL Version 2.6C, Some changes of the threads cancelation. ** 19-FEB-2003 RRL Version 2.6D, Fixed a bug with reseting of the server. ** 14-MAR-2003 RRL Version 2.6E, RESET & RESTART -> RESTART. ** 17-MAR-2003 RRL Version 2.7, Now it's just full-function version. ** 4-JUN-2003 RRL Version 2.7A, Now Client-Id is a special non-protocol attribute. ** 18-AUG-2003 RRL Version 2.7B, fixed bug in the RAD_UTIL.C. ** 30-SEP-2003 RRL Version 2.7C, added Auth-Type = Digest support. ** 23-OCT-2003 RRL Version 2.7D, added client's /ACCEPT_REALM and /REJECT_REALM options. ** 6-NOV-2003 RRL Version 2.7E, restore RESET functionality. ** 25-NOV-2003 RRL Version 2.7G, backup/proxy/forwarding. ** 12-FEB-2003 RRL Version 2.7H, Calling Station Id = IMSI. ** 16-FEB-2004 RRL Version 2.7I, Added loging to SYSLOG ** 19-FEB-2004 RRL Version 2.7I, Added RADIUS_THSTACKSZ logicals. ** 31-MAY-2004 RRL Version 2.7K, Added INCLUDE directive in the ** RADIUS_CONFIG file syntax. ** 26-AUG-2004 RRL Version 3.0A, Removed RAD$DUALPORT, RAD$56K, RAD$ISDN rights id ** and corresp. code. ** 1-OCT-2004 RRL Version 3.0B, Added Calling-Station-Id to responses to help Cisco CSG ** tracks users session. ** 13-APR-2005 RRL Version 3.1A, Added A12 support. ** 20-MAY-2004 RRL Version 3.1B, Added Client Group ID handling ** 4-OCT-2006 RRL Version 3.1C, Fixed bug in realm handling. ** 31-OCT-2006 RRL Fixed bug in RAD_CONF module in comparing routine. ** 6-AUG-2008 RRL Introduced a support RADIUS_DB. ** 13-OCT-2008 RRL Up version to 4.0A. ** 26-FEB-2009 RRL Added maintaining of statistical counters. ** 19-MAY-2011 RRL 4.0C, rfc2868, RADIUS Attributes for Tunnel Protocol Support ** 10-NOV-2011 RRL 5.0A, Added templates support (Template-Id attrubute). ** ** {@tbs@}... **-- */ /* ** ** INCLUDE FILES ** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "syslogdef.h" #define __NEW_STARLET 1 #include #include "raddef.h" #include "radius.h" /* ** ** MACRO DEFINITIONS ** */ #ifdef __VAX char arch [] = "VAX"; #endif #ifdef __ALPHA char arch [] = "Alpha"; #endif #ifdef __ia64 char arch [] = "IA64"; #endif /* ** EXTERNAL MODULES NAMES AND ENRTY POINTS DECLARATIONS */ $DESCRIPTOR(rad_ext_auth, "RADIUS_EXT_AUTH"); $DESCRIPTOR(rad_ext_acct, "RADIUS_EXT_ACCT"); $DESCRIPTOR(init_dsc, "INIT"); $DESCRIPTOR(cleanup_dsc, "CLEANUP"); $DESCRIPTOR(auth_dsc, "AUTHORIZE"); $DESCRIPTOR(acct_dsc, "ACCOUNTING"); /* ** ** SYSLOG API context ** */ extern void *slogctx = NULL; /* **++ ** FUNCTIONAL DESCRIPTION: ** ** Performs an initalization and start RADIUS-VMS server. ** ** FORMAL PARAMETERS: ** ** None ** ** RETURN VALUE: ** ** VMS and RADIUS-VMS specific condition code ** ** **-- */ int main (void) { int status = 0,numthreads = 3,idx,cmd_status,thstacksz = 96000; struct timespec tm_wait = {5,0}; char buf [ 256 ],*cp; pthread_cond_t cmd_cond; pthread_mutex_t cmd_lock; /* ** */ if ( cp = get_logname("RADIUS_SYSLOG",buf,sizeof(buf)) ) { char host [ 128 ], port [ 32 ]; if ( sscanf(buf,"%[^:]:%[^]",host,port) ) if ( !(1 & (status = syslog_init(&slogctx,host,atoi(port)))) ) rad_log(status); } /* ** Set reenterancy flag for C RTL */ decc$set_reentrancy(C$C_MULTITHREAD); /* ** Initalize control stuff */ $PTHREAD_COND_INIT(&cmd_cond); $PTHREAD_MUTEX_INIT(&cmd_lock); if ( cp = get_logname("RADIUS_THSTACKSZ",buf,sizeof(buf)) ) thstacksz = atoi(cp); /* ** Create a thread attribute to set a stack size */ #ifdef __VAX status = pthread_attr_create(&tattr); status = pthread_attr_setstacksize(&tattr,max(96000,thstacksz)); #else status = pthread_attr_init(&tattr); status = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_JOINABLE); status = pthread_attr_setstacksize(&tattr,max(96000,thstacksz)); #endif /* ** Put to SYS$OUTPUT a version information,architecture,build date */ rad_log(RAD_MAIN_VERSION,RADIUS_VMS_VERSION,arch,__DATE__); /* ** Get configuration variables and flags */ debug_flag = get_logname("RADIUS_DEBUG",buf,sizeof(buf))?1:0; pwd_expired = get_logname("RADIUS_PWD_EXPIRED",buf,sizeof(buf))?1:0; restricted = get_logname("RADIUS_ALLOW_RECTRICTED",buf,sizeof(buf))?1:0; dns_lookup = get_logname("RADIUS_DNS_LOOKUP",buf,sizeof(buf))?1:0; session_tmo_flag= get_logname("RADIUS_SESSIONTMO",buf,sizeof(buf))?1:0; if ( cp = get_logname("RADIUS_OPCOMLVL",buf,sizeof(buf)) ) opcomlvl = atoi(cp); else opcomlvl = 0; if ( cp = get_logname("RADIUS_NUMTHREADS",buf,sizeof(buf)) ) numthreads = atoi(cp); else numthreads = 1; numthreads = min(MAXTHREADS,numthreads); /* ** Initialize the dictionary */ if( !(1 & (status = dict_init())) ) sys$exit (status); /* ** Load Templates */ if( !(1 & (status = tmpl_init())) ) lib$signal(status); /* ** Load configuration */ if( !(1 & (status = rad_conf())) ) sys$exit (status); /* ** Get a main IP address */ if ( cp = get_logname("UCX$INET_HOSTADDR",buf,sizeof(buf)) ) host_ip = inet_addr(cp); else if ( cp = get_logname("TCPIP$INET_HOSTADDR",buf,sizeof(buf)) ) host_ip = inet_addr(cp); /* ** Initialize of external modules (if any) */ if ( get_logname("RADIUS_EXT_AUTH",buf,sizeof(buf)) ) { DEBUG("Loading external AUTH module...\n"); lib$find_image_symbol(&rad_ext_auth,&init_dsc,&rad_ext_auth_init,0,0); lib$find_image_symbol(&rad_ext_auth,&auth_dsc,&rad_ext_auth_auth,0,0); lib$find_image_symbol(&rad_ext_auth,&cleanup_dsc,&rad_ext_auth_cleanup,0,0); } if ( get_logname("RADIUS_EXT_ACCT",buf,sizeof(buf)) ) { DEBUG("Loading external ACCT module...\n"); lib$find_image_symbol(&rad_ext_acct,&init_dsc,&rad_ext_acct_init,0,0); lib$find_image_symbol(&rad_ext_acct,&acct_dsc,&rad_ext_acct_acct,0,0); lib$find_image_symbol(&rad_ext_acct,&cleanup_dsc,&rad_ext_acct_cleanup,0,0); } /* ** Initialize RADIUS homes (if any) */ for (idx = 0;idx < maxhomes;idx++) { if ( homes[idx].auth_sock.sin_addr.s_addr || homes[idx].auth_sock.sin_port ) { ipaddr2str(buf,ntohl(homes[idx].auth_sock.sin_addr.s_addr)); if ( !(1 & (status = netio_open(&homes[idx].auth_chan, &homes[idx].auth_sock,homes[idx].recvbfsz))) ) { rad_log (RAD_MAIN_ERRNETOPEN,buf,ntohs(homes[idx].auth_sock.sin_port),status); homes[idx].auth_chan = 0; } else rad_log (RAD_MAIN_NETOPEN,buf,ntohs(homes[idx].auth_sock.sin_port)); } if ( homes[idx].acct_sock.sin_addr.s_addr || homes[idx].acct_sock.sin_port ) { ipaddr2str(buf,ntohl(homes[idx].acct_sock.sin_addr.s_addr)); if ( !(1 & (status = netio_open(&homes[idx].acct_chan, &homes[idx].acct_sock,homes[idx].recvbfsz))) ) { rad_log (RAD_MAIN_ERRNETOPEN,buf,ntohs(homes[idx].acct_sock.sin_port),status); homes[idx].acct_chan = 0; } else rad_log (RAD_MAIN_NETOPEN,buf,ntohs(homes[idx].acct_sock.sin_port)); } } /* ** Initalize VM zones */ if ( !(1 & rad_init_vm (maxhomes*numthreads)) ) sys$exit (SS$_ABORT); /* ** Clear threads exit flag */ exit_flag = 0; /* ** Performs an initalization of external modules (if configured) */ if ( rad_ext_acct_init && !(1 & (status = rad_ext_acct_init(&extacctcontext))) ) { rad_log(RAD_MAIN_ERREXTINIT,status); rad_ext_acct_acct = NULL; rad_ext_acct_cleanup = NULL; } if ( rad_ext_auth_init && !(1 & (status = rad_ext_auth_init(&extauthcontext))) ) { rad_log(RAD_MAIN_ERREXTINIT,status); rad_ext_auth_auth = NULL; rad_ext_auth_cleanup = NULL; } /* ** Opening accounting file */ if( !(1 & radacct_open ())) sys$exit (SS$_ABORT); /* ** Starting an accounting and authorization threads ** for an every home */ for ( idx = 0;idx < maxhomes;idx++) { if ( homes[idx].acct_chan ) radacct_start(homes[idx].acct_chan,numthreads,idx); if ( homes[idx].auth_chan ) radauth_start(homes[idx].auth_chan,numthreads,idx); } /* ** Waiting for control events */ if ( !(1 & rad_cp_init(pthread_cond_signal_int_np,&cmd_cond,&cmd_status)) ) sys$exit (SS$_ABORT); do { int st; struct timespec delta= {10,0},abstime; /* ** Wait for a condition or a timeout */ st = pthread_mutex_lock(&cmd_lock); st = pthread_get_expiration_np (&delta,&abstime); status = pthread_cond_timedwait( &cmd_cond,&cmd_lock,&abstime); st = pthread_mutex_unlock(&cmd_lock); /* ** Log the control event */ if ( cmd_status ) rad_log(cmd_status); if ( cmd_status == RAD_MAIN_CMD_RSET ) { radauth_setflag(0); cmd_status = 0; status = tmpl_init(); } /* ** Put a statistic to be read by external SNMP ** subagent. */ // rad_putstat(); } while (!cmd_status); if ( !(1 & (status = rad_cp_shut())) ) rad_log(status); /* ** Received a control event, set exit flag for all threads, ** wait for concelation of all threads */ exit_flag = 1; pthread_delay_np(&tm_wait); /* ** Close all network I/O channels and stop threads */ for (idx = 0;idx < maxhomes;idx++) { if ( homes[idx].auth_chan ) { if ( !(1 & (status = netio_close(homes[idx].auth_chan))) ) lib$signal(status); radauth_stop(homes[idx].auth_chan,numthreads,idx); } if ( homes[idx].acct_chan ) { if ( !(1 & (status = netio_close(homes[idx].acct_chan))) ) lib$signal(status); radacct_stop(homes[idx].acct_chan,numthreads,idx); } } /* ** Close accounting file */ radacct_close(); /* ** Performs a shutdown task for external modules */ if ( rad_ext_auth_cleanup && extauthcontext && !(1 & (status = rad_ext_auth_cleanup(&extauthcontext))) ) rad_log(RAD_MAIN_ERREXTCLEANUP,status); if ( rad_ext_acct_cleanup && extacctcontext && !(1 & (status = rad_ext_acct_cleanup(&extacctcontext))) ) rad_log(RAD_MAIN_ERREXTCLEANUP,status); if ( slogctx && syslog_shut(slogctx) ) lib$signal(status); switch ( cmd_status ) { case RAD_MAIN_CMD_RSTA: status = 0x0000FFFF; break; case RAD_MAIN_CMD_SHUT: status = SS$_NORMAL; default: } return status; }