radiusd-livingston-2.1/0042755000175000017500000000000006734304671013033 5ustar pmpmradiusd-livingston-2.1/raddb/0042755000175000017500000000000006734271003014077 5ustar pmpmradiusd-livingston-2.1/raddb/clients0100644000175000017500000000103606732444511015462 0ustar pmpm#--------------------------------------------------------------------------- # # @(#)clients 1.1 2/21/96 Copyright 1991 Livingston Enterprises Inc # #--------------------------------------------------------------------------- # # This file contains a list of clients which are allowed to # make authentication requests and their encryption key. # The first field is a valid hostname. # The second field (seperated by blanks or tabs) is the # encryption key. # #Client Name Key #---------------- ------------------- portmaster1 testing123 radiusd-livingston-2.1/raddb/dictionary0100644000175000017500000003136006734265644016203 0ustar pmpm#--------------------------------------------------------------------------- # # $Id: dictionary,v 1.6 1999/06/23 23:20:04 cdr Exp $ Copyright 1991-1999 Lucent Technologies Inc # #--------------------------------------------------------------------------- # # This file contains dictionary translations for parsing # requests and generating responses. All transactions are # composed of Attribute/Value Pairs. The value of each attribute # is specified as one of 4 data types. Valid data types are: # # string - 0-253 octets # ipaddr - 4 octets in network byte order # integer - 32 bit value in big endian order (high byte first) # date - 32 bit value in big endian order - seconds since # 00:00:00 GMT, Jan. 1, 1970 # # Enumerated values are stored in the user file with dictionary # VALUE translations for easy administration. # # Example: # # ATTRIBUTE VALUE # --------------- ----- # Framed-Protocol = PPP # 7 = 1 (integer encoding) # # # Obsolete names for backwards compatibility with older users files # If you want RADIUS accounting logs to use these obsolete names # instead of the current ones, move this section to the end of the # dictionary file and kill and restart radiusd # If you don't have a RADIUS 1.16 users file that you're still using, # you can delete or ignore this section. # ATTRIBUTE Client-Id 4 ipaddr ATTRIBUTE Client-Port-Id 5 integer ATTRIBUTE User-Service-Type 6 integer ATTRIBUTE Framed-Address 8 ipaddr ATTRIBUTE Framed-Netmask 9 ipaddr ATTRIBUTE Framed-Filter-Id 11 string ATTRIBUTE Login-Host 14 ipaddr ATTRIBUTE Login-Port 16 integer ATTRIBUTE Old-Password 17 string ATTRIBUTE Port-Message 18 string ATTRIBUTE Dialback-No 19 string ATTRIBUTE Dialback-Name 20 string ATTRIBUTE Challenge-State 24 string VALUE Service-Type Dialback-Login-User 3 VALUE Service-Type Dialback-Framed-User 4 VALUE Service-Type Shell-User 6 VALUE Framed-Compression Van-Jacobsen-TCP-IP 1 VALUE Auth-Type Unix 1 # # END of obsolete names for backwards compatibility # # # Standard Attributes # ATTRIBUTE User-Name 1 string ATTRIBUTE Password 2 string ATTRIBUTE CHAP-Password 3 string ATTRIBUTE NAS-IP-Address 4 ipaddr ATTRIBUTE NAS-Port 5 integer ATTRIBUTE Service-Type 6 integer ATTRIBUTE Framed-Protocol 7 integer ATTRIBUTE Framed-IP-Address 8 ipaddr ATTRIBUTE Framed-IP-Netmask 9 ipaddr ATTRIBUTE Framed-Routing 10 integer ATTRIBUTE Filter-Id 11 string ATTRIBUTE Framed-MTU 12 integer ATTRIBUTE Framed-Compression 13 integer ATTRIBUTE Login-IP-Host 14 ipaddr ATTRIBUTE Login-Service 15 integer ATTRIBUTE Login-TCP-Port 16 integer # Attribute 17 has not been assigned ATTRIBUTE Reply-Message 18 string ATTRIBUTE Callback-Number 19 string ATTRIBUTE Callback-Id 20 string ATTRIBUTE Framed-Route 22 string ATTRIBUTE Framed-IPX-Network 23 ipaddr ATTRIBUTE State 24 string ATTRIBUTE Class 25 string ATTRIBUTE Vendor-Specific 26 string ATTRIBUTE Session-Timeout 27 integer ATTRIBUTE Idle-Timeout 28 integer ATTRIBUTE Termination-Action 29 integer ATTRIBUTE Called-Station-Id 30 string ATTRIBUTE Calling-Station-Id 31 string ATTRIBUTE NAS-Identifier 32 string ATTRIBUTE Proxy-State 33 string ATTRIBUTE Login-LAT-Service 34 string ATTRIBUTE Login-LAT-Node 35 string ATTRIBUTE Login-LAT-Group 36 string ATTRIBUTE Framed-AppleTalk-Link 37 integer ATTRIBUTE Framed-AppleTalk-Network 38 integer ATTRIBUTE Framed-AppleTalk-Zone 39 string ATTRIBUTE Acct-Status-Type 40 integer ATTRIBUTE Acct-Delay-Time 41 integer ATTRIBUTE Acct-Input-Octets 42 integer ATTRIBUTE Acct-Output-Octets 43 integer ATTRIBUTE Acct-Session-Id 44 string ATTRIBUTE Acct-Authentic 45 integer ATTRIBUTE Acct-Session-Time 46 integer ATTRIBUTE Acct-Input-Packets 47 integer ATTRIBUTE Acct-Output-Packets 48 integer ATTRIBUTE Acct-Terminate-Cause 49 integer ATTRIBUTE Acct-Multi-Session-Id 50 string ATTRIBUTE Acct-Link-Count 51 integer ATTRIBUTE Acct-Input-Gigawords 52 integer ATTRIBUTE Acct-Output-Gigawords 53 integer # Attribute 54 has not been assigned ATTRIBUTE Event-Timestamp 55 integer # Attributes 55-59 have not been assigned ATTRIBUTE CHAP-Challenge 60 string ATTRIBUTE NAS-Port-Type 61 integer ATTRIBUTE Port-Limit 62 integer ATTRIBUTE Login-LAT-Port 63 string ATTRIBUTE Tunnel-Type 64 integer ATTRIBUTE Tunnel-Medium-Type 65 integer ATTRIBUTE Tunnel-Client-Endpoint 66 string ATTRIBUTE Tunnel-Server-Endpoint 67 string ATTRIBUTE Acct-Tunnel-Connection 68 string ATTRIBUTE Tunnel-Password 69 string ATTRIBUTE ARAP-Password 70 string ATTRIBUTE ARAP-Features 71 string ATTRIBUTE ARAP-Zone-Access 72 integer ATTRIBUTE ARAP-Security 73 integer ATTRIBUTE ARAP-Security-Data 74 string ATTRIBUTE Password-Retry 75 integer ATTRIBUTE Prompt 76 integer ATTRIBUTE Connect-Info 77 string ATTRIBUTE Configuration-Token 78 string ATTRIBUTE EAP-Message 79 string ATTRIBUTE Signature 80 string ATTRIBUTE Tunnel-Private-Group-ID 81 string ATTRIBUTE Tunnel-Assignment-ID 82 string ATTRIBUTE Tunnel-Preference 83 integer ATTRIBUTE ARAP-Challenge-Response 84 string ATTRIBUTE Acct-Interim-Interval 85 integer ATTRIBUTE Acct-Tunnel-Packets-Lost 86 integer ATTRIBUTE NAS-Port-Id 87 string ATTRIBUTE Framed-Pool 88 string # # Integer Translations # # Service Types VALUE Service-Type Login-User 1 VALUE Service-Type Framed-User 2 VALUE Service-Type Callback-Login-User 3 VALUE Service-Type Callback-Framed-User 4 VALUE Service-Type Outbound-User 5 VALUE Service-Type Administrative-User 6 VALUE Service-Type NAS-Prompt-User 7 VALUE Service-Type Authenticate-Only 8 VALUE Service-Type Callback-NAS-Prompt 9 VALUE Service-Type Call-Check 10 VALUE Service-Type Callback-Administrative 11 # # Call-Check-User was used in ComOS 3.8b16 and before; replaced by Call-Check # VALUE Service-Type Call-Check-User 129 # Framed Protocols VALUE Framed-Protocol PPP 1 VALUE Framed-Protocol SLIP 2 VALUE Framed-Protocol ARAP 3 VALUE Framed-Protocol GANDALF-SLMLP 4 VALUE Framed-Protocol XYLOGICS-IPX-SLIP 5 VALUE Framed-Protocol X75 6 # Framed Routing Values VALUE Framed-Routing None 0 VALUE Framed-Routing Broadcast 1 VALUE Framed-Routing Listen 2 VALUE Framed-Routing Broadcast-Listen 3 # Framed Compression Types VALUE Framed-Compression None 0 VALUE Framed-Compression Van-Jacobson-TCP-IP 1 VALUE Framed-Compression IPX-Header 2 VALUE Framed-Compression Stac-LZS 3 # Login Services VALUE Login-Service Telnet 0 VALUE Login-Service Rlogin 1 VALUE Login-Service TCP-Clear 2 VALUE Login-Service PortMaster 3 VALUE Login-Service LAT 4 VALUE Login-Service X.25-PAD 5 VALUE Login-Service X.25-T3POS 6 VALUE Login-Service TCP-Clear-Quiet 8 # Status Types VALUE Acct-Status-Type Start 1 VALUE Acct-Status-Type Stop 2 VALUE Acct-Status-Type Interim-Update 3 VALUE Acct-Status-Type Accounting-On 7 VALUE Acct-Status-Type Accounting-Off 8 VALUE Acct-Status-Type Tunnel-Start 9 VALUE Acct-Status-Type Tunnel-Stop 10 VALUE Acct-Status-Type Tunnel-Reject 11 VALUE Acct-Status-Type Tunnel-Link-Start 12 VALUE Acct-Status-Type Tunnel-Link-Stop 13 VALUE Acct-Status-Type Tunnel-Link-Reject 14 VALUE Acct-Status-Type Failed 15 # Authentication Types VALUE Acct-Authentic RADIUS 1 VALUE Acct-Authentic Local 2 VALUE Acct-Authentic Remote 3 # Termination Options VALUE Termination-Action Default 0 VALUE Termination-Action RADIUS-Request 1 # NAS Port Types VALUE NAS-Port-Type Async 0 VALUE NAS-Port-Type Sync 1 VALUE NAS-Port-Type ISDN 2 VALUE NAS-Port-Type ISDN-V120 3 VALUE NAS-Port-Type ISDN-V110 4 VALUE NAS-Port-Type Virtual 5 VALUE NAS-Port-Type PIAFS 6 VALUE NAS-Port-Type HDLC-Clear-Channel 7 VALUE NAS-Port-Type X.25 8 VALUE NAS-Port-Type X.75 9 VALUE NAS-Port-Type G.3-Fax 10 VALUE NAS-Port-Type SDSL 11 VALUE NAS-Port-Type ADSL-CAP 12 VALUE NAS-Port-Type ADSL-DMT 13 VALUE NAS-Port-Type IDSL 14 VALUE NAS-Port-Type Ethernet 15 # Acct Terminate Causes VALUE Acct-Terminate-Cause User-Request 1 VALUE Acct-Terminate-Cause Lost-Carrier 2 VALUE Acct-Terminate-Cause Lost-Service 3 VALUE Acct-Terminate-Cause Idle-Timeout 4 VALUE Acct-Terminate-Cause Session-Timeout 5 VALUE Acct-Terminate-Cause Admin-Reset 6 VALUE Acct-Terminate-Cause Admin-Reboot 7 VALUE Acct-Terminate-Cause Port-Error 8 VALUE Acct-Terminate-Cause NAS-Error 9 VALUE Acct-Terminate-Cause NAS-Request 10 VALUE Acct-Terminate-Cause NAS-Reboot 11 VALUE Acct-Terminate-Cause Port-Unneeded 12 VALUE Acct-Terminate-Cause Port-Preempted 13 VALUE Acct-Terminate-Cause Port-Suspended 14 VALUE Acct-Terminate-Cause Service-Unavailable 15 VALUE Acct-Terminate-Cause Callback 16 VALUE Acct-Terminate-Cause User-Error 17 VALUE Acct-Terminate-Cause Host-Request 18 # Tunnel Types VALUE Tunnel-Type PPTP 1 VALUE Tunnel-Type L2F 2 VALUE Tunnel-Type L2TP 3 VALUE Tunnel-Type ATMP 4 VALUE Tunnel-Type VTP 5 VALUE Tunnel-Type AH 6 VALUE Tunnel-Type IP-IP 7 VALUE Tunnel-Type MIN-IP-IP 8 VALUE Tunnel-Type ESP 9 VALUE Tunnel-Type GRE 10 VALUE Tunnel-Type DVS 11 VALUE Tunnel-Type IP-in-IP 12 # Tunnel Medium Types VALUE Tunnel-Medium-Type IP 1 VALUE Tunnel-Medium-Type IP6 2 VALUE Tunnel-Medium-Type NSAP 3 VALUE Tunnel-Medium-Type HDLC 4 VALUE Tunnel-Medium-Type BBN 5 VALUE Tunnel-Medium-Type Ether_802 6 VALUE Tunnel-Medium-Type E.163 7 VALUE Tunnel-Medium-Type E.164 8 VALUE Tunnel-Medium-Type F.69 9 VALUE Tunnel-Medium-Type X.121 10 VALUE Tunnel-Medium-Type IPX 11 VALUE Tunnel-Medium-Type AppleTalk 12 VALUE Tunnel-Medium-Type DECnet 13 VALUE Tunnel-Medium-Type Banyan 14 # Prompt VALUE Prompt No-Echo 0 VALUE Prompt Echo 1 # # Vendor-Specific attributes use the SMI Network Management Private # Enterprise Code from the "Assigned Numbers" RFC # VENDOR Livingston 307 VENDOR Lucent 1751 # # Livingston Vendor-Specific Attributes (requires ComOS 3.8 and RADIUS 2.1) # ATTRIBUTE LE-Terminate-Detail 2 string Livingston ATTRIBUTE LE-Advice-of-Charge 3 string Livingston ATTRIBUTE LE-Connect-Detail 4 string Livingston ATTRIBUTE LE-IP-Pool 6 string Livingston ATTRIBUTE LE-IP-Gateway 7 ipaddr Livingston ATTRIBUTE LE-Modem-Info 8 string Livingston ATTRIBUTE LE-IPSec-Log-Options 9 integer Livingston ATTRIBUTE LE-IPSec-Deny-Action 10 integer Livingston ATTRIBUTE LE-IPSec-Active-Profile 11 string Livingston ATTRIBUTE LE-IPSec-Outsource-Profile 12 string Livingston ATTRIBUTE LE-IPSec-Passive-Profile 13 string Livingston ATTRIBUTE LE-NAT-TCP-Session-Timeout 14 integer Livingston ATTRIBUTE LE-NAT-Other-Session-Timeout 15 integer Livingston ATTRIBUTE LE-NAT-Log-Options 16 integer Livingston ATTRIBUTE LE-NAT-Sess-Dir-Fail-Action 17 integer Livingston ATTRIBUTE LE-NAT-Inmap 18 string Livingston ATTRIBUTE LE-NAT-Outmap 19 string Livingston ATTRIBUTE LE-NAT-Outsource-Inmap 20 string Livingston ATTRIBUTE LE-NAT-Outsource-Outmap 21 string Livingston ATTRIBUTE LE-Admin-Group 22 string Livingston ATTRIBUTE LE-Multicast-Client 23 integer Livingston VALUE LE-IPSec-Deny-Action Drop 1 VALUE LE-IPSec-Deny-Action ICMP-Reject 2 VALUE LE-IPSec-Deny-Action Pass-Through 3 VALUE LE-IPsec-Log-Options SA-Success-On 1 VALUE LE-IPSec-Log-Options SA-Failure-On 2 VALUE LE-IPSec-Log-Options Console-On 3 VALUE LE-IPSec-Log-Options Syslog-On 4 VALUE LE-IPSec-Log-Options SA-Success-Off 5 VALUE LE-IPSec-Log-Options SA-Failure-Off 6 VALUE LE-IPSec-Log-Options Console-Off 7 VALUE LE-IPSec-Log-Options Syslog-Off 8 VALUE LE-NAT-Sess-Dir-Fail-Action Drop 1 VALUE LE-NAT-Sess-Dir-Fail-Action ICMP-Reject 2 VALUE LE-NAT-Sess-Dir-Fail-Action Pass-Through 3 VALUE LE-NAT-Log-Options Session-Success-On 1 VALUE LE-NAT-Log-Options Session-Failure-On 2 VALUE LE-NAT-Log-Options Console-On 3 VALUE LE-NAT-Log-Options Syslog-On 4 VALUE LE-NAT-Log-Options Success-Off 5 VALUE LE-NAT-Log-Options Failure-Off 6 VALUE LE-NAT-Log-Options Console-Off 7 VALUE LE-NAT-Log-Options Syslog-Off 8 VALUE LE-Multicast-Client On 1 # # Non-Protocol Attributes # These attributes are used internally by the server # ATTRIBUTE Expiration 21 date ATTRIBUTE Auth-Type 1000 integer ATTRIBUTE Menu 1001 string ATTRIBUTE Termination-Menu 1002 string ATTRIBUTE Prefix 1003 string ATTRIBUTE Suffix 1004 string ATTRIBUTE Group 1005 string ATTRIBUTE Crypt-Password 1006 string ATTRIBUTE Connect-Rate 1007 integer # # Non-Protocol Integer Translations # VALUE Auth-Type Local 0 VALUE Auth-Type System 1 VALUE Auth-Type SecurID 2 VALUE Auth-Type Crypt-Local 3 VALUE Auth-Type Reject 4 VALUE Auth-Type ActivCard 5 # # Configuration Values # comment out these two lines to turn account expiration off # VALUE Server-Config Password-Expiration 30 VALUE Server-Config Password-Warning 5 radiusd-livingston-2.1/raddb/menus/0042755000175000017500000000000006732444511015232 5ustar pmpmradiusd-livingston-2.1/raddb/menus/menu10100644000175000017500000000227606732444511016204 0ustar pmpmmenu *** This is a test Menu coming from RADIUS *** Menus can contain up to 1500 bytes of data. They can contain any non-null characters. Option selections require an exact match. If case insensitivity is required, enter the menu choices twice, once in upper and once in lower case. Please enter an option: 1 Start PPP session 2 Start CSLIP session 3 Start SLIP session 4 Start login session 5 Go to second menu 6 Exit Option: end 1 Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-Routing = None, Framed-Compression = Van-Jacobson-TCP-IP, Framed-MTU = 1500 # 2 Service-Type = Framed-User, Framed-Protocol = SLIP Framed-IP-Address = 255.255.255.254, Framed-Routing = None, Framed-Compression = Van-Jacobson-TCP-IP, Framed-MTU = 1006 # 3 Service-Type = Framed-User, Framed-Protocol = SLIP Framed-IP-Address = 255.255.255.254, Framed-Routing = None, Framed-Compression = None, Framed-MTU = 1006 # 4 Service-Type = Login-User, Login-Service = PortMaster, Termination-Menu = "menu1" # 5 Menu = "menu2" # 6 Menu = "EXIT" DEFAULT Menu = "menu1" radiusd-livingston-2.1/raddb/menus/menu20100644000175000017500000000160406732444511016177 0ustar pmpmmenu *** This is a test Menu coming from RADIUS *** Menus can call other menus. This menu is called when option 5 of menu1 is selected. Menu choices can be words as well as numbers. Please enter an option: ra Connect to host ra sol Connect to host sol weevil Connect to host weevil top Return to top level menu quit Quit Option: end ra Service-Type = Login-User, Login-IP-Host = ra, Login-Service = Rlogin, Termination-Menu = "menu2" # sol Service-Type = Login-User, Login-IP-Host = sol, Login-Service = Rlogin, Termination-Menu = "menu2" # weevil Service-Type = Login-User, Login-IP-Host = weevil, Login-Service = Rlogin, Termination-Menu = "menu2" # top Menu = "menu1" # quit Menu = "EXIT" # DEFAULT Menu = "menu2" radiusd-livingston-2.1/raddb/proxy0100644000175000017500000000217206732444511015204 0ustar pmpm#--------------------------------------------------------------------------- # # @(#)proxy 1.2 3/1/98 Copyright 1997 Livingston Enterprises Inc # #--------------------------------------------------------------------------- # # This file contains a list of remote servers to forward to # The first field is a valid hostname or IP address # The second field (seperated by blanks or tabs) is the shared secret # The third field is the named or numeric authentication realm # The fourth field can contain the optional RADIUS UDP Port number of # the remote server, the RADIUS and RADIUS Accounting Port numbers, # and any of following optional keywords: # # old Strip realm and do not attach Proxy-State when forwarding # secure Allow remote server to authorize admin logins for your client # ipass Use the ipass protocol # #server name key realm ports and keywords #------------ --------------- ----------- --------------- #rad.edu.com chsebetterth edu.com #rad7.com.net lx4zDFapa3ep com.net 1645 1646 old #radius.edu.net eajsdfljasep 5551234 1812 1813 secure #eg.edu.net e997asepdflj edu.net old secure #ipass.com bigbigsecret DEFAULT ipass radiusd-livingston-2.1/raddb/users0100644000175000017500000000733606732444511015173 0ustar pmpm#--------------------------------------------------------------------------- # # @(#)users 1.2 5/20/97 Copyright 1991, 1997 Livingston Enterprises Inc # #--------------------------------------------------------------------------- # # This file contains security and configuration information for # each user. The first field is the user's name and can be up to # 8 characters in length. This is followed (on the same line) # with the list of authentication requirements for that user. # This can include password, comm server name, comm server port # number, and an expiration date of the user's password. When an # authentication request is received from the comm server, these # values are tested. Special users named "DEFAULT", "DEFAULT2", # "DEFAULT3" can be created (and should be placed at the end of # the user file) to specify what to do with users not contained # in the user file. # # Indented (with the tab character) lines following the first # line indicate the configuration values to be passed back to # the comm server to allow the initiation of a user session. # This can include things like the PPP configuration values # or the host to log the user onto. # # Delete or comment out these examples before using this file! bob Password = "testing", Expiration = "Dec 24 1995" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-Routing = None, Filter-Id = "std.ppp", Framed-MTU = 1500, Framed-Compression = Van-Jacobson-TCP-IP mary Password = "moretest" Service-Type = Login-User, Login-IP-Host = 172.16.2.7, Login-Service = PortMaster stan Password = "callme" Service-Type = Callback-Login-User, Login-IP-Host = timeshare1, Login-Service = PortMaster, Callback-Number = "9,1-800-555-1234" # # Example Menu User # bar Auth-Type = System Menu = "menu1" # # The following section illustrates how to use the new features in RADIUS 1.18 # If all your users' passwords are in your UNIX passwd file, you could even # delete all the lines above and just run with the following section. # # Username Palex runs PPP if alex's UNIX password matches # DEFAULT Auth-Type = System, Prefix = "P" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-MTU = 1500 # Username Salex runs SLIP if alex's UNIX password matches DEFAULT Auth-Type = System, Prefix = "S" Service-Type = Framed-User, Framed-Protocol = SLIP, Framed-IP-Address = 255.255.255.254, Framed-Compression = None # Username Calex runs CSLIP if alex's UNIX password matches DEFAULT Auth-Type = System, Prefix = "C" Service-Type = Framed-User, Framed-Protocol = SLIP, Framed-IP-Address = 255.255.255.254, Framed-Compression = Van-Jacobson-TCP-IP # Username alex%ppp runs PPP if alex's UNIX password matches DEFAULT Auth-Type = System, Suffix = "%ppp" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-MTU = 1500 # Username alex%slip runs SLIP if alex's UNIX password matches DEFAULT Auth-Type = System, Suffix = "%slip" Service-Type = Framed-User, Framed-Protocol = SLIP, Framed-IP-Address = 255.255.255.254 Framed-Compression = None # Username alex%cslip runs CSLIP if alex's UNIX password matches DEFAULT Auth-Type = System, Suffix = "%cslip" Service-Type = Framed-User, Framed-Protocol = SLIP, Framed-IP-Address = 255.255.255.254, Framed-Compression = Van-Jacobson-TCP-IP # Username alex runs PPP if alex uses PAP to authenticate and port autodetects DEFAULT Auth-Type = System, Framed-Protocol = PPP Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-MTU = 1500 # # Anything else uses Rlogin to the host set for that port # DEFAULT Auth-Type = System Service-Type = Login-User, Login-Service = Rlogin radiusd-livingston-2.1/raddb/config.aeg.example0100644000175000017500000001066106732444512017460 0ustar pmpm# Rename this file to config.aeg after installing new ActivCard server # # ----------------------------------------------------------------- # This file contains the configuration information necessary for the # RADIUS server to connect to the ActivEngine, which is the # ActivCard Authentication Server. # ----------------------------------------------------------------- # ----------------------------------------------------------------- # ACTIVCARD_APPLICATION: APPLICATION_ID # # ActivCards contain up to four slots. Each slot contains a set # of independent DES keys and parameters, so that in practice an # ActivCard is equivalent to four «Tokens». Each of those «Tokens» # is called a slot and can be used to authenticate through an application # to a distinct ActivEngine. The concept that the ActivEngine uses to # decide which slot is to be used to verify a dynamic password (ultimately # which key among the set of keys stored for this token) is # the «Application» : Application (Server) -> Slot (Token) # # The following specifies the application to be used to determine the # token slot associated with RADIUS authentication requests from # the RADIUS server. # ----------------------------------------------------------------- ACTIVCARD_APPLICATION: RADIUS # ----------------------------------------------------------------- # ACTIVCARD_CHALLENGE: challenge_request_keyword # The ActivCards support simultaneously two authentication codes # for each given slot. One is a patented time/event synchronous mode # in which the user just types the one-time password displayed by his token # instead of the static vulnerable password he was used to. The other is # the standard X9.9, challenge/response mode. # ActivCard’s users can choose which mode they want to use by # typing a keyword at the RADIUS password prompt: # login: sam # password: challenge_request_keyword # Upon reception of this keyword the ActivCard component embedded in the # RADIUS server will switch to challenge/response mode and issue a # challenge (a very good quality random number), and the user will be prompted # for a dynamic password: # login: sam # password: challenge_request_keyword # # Challenge/Response Authentication requested... # Challenge: 12345678 # Response: # The user has to type the challenge into his token and type at the prompt the # dynamic password produced by the token for that challenge. # ----------------------------------------------------------------- ACTIVCARD_CHALLENGE: challenge # ----------------------------------------------------------------- # ACTIVCARD_HOST: 192.168.15.60 # The following parameter indicates the ip address of the machine where the # ActivEngine is located. # ----------------------------------------------------------------- ACTIVCARD_HOST: 192.168.15.60 # ----------------------------------------------------------------- # ACTIVCARD_AUTHPORT: 8866 # The following parameter specifies the port to which the ActivEngine # will be listening for authentication requests. # ----------------------------------------------------------------- ACTIVCARD_AUTHPORT: 8866 # ----------------------------------------------------------------- # ACTIVCARD_SESSTIMEOUT: 25 # This parameter specifies the timeout value to use when the RADIUS # server connects to the ActivEngine. # ----------------------------------------------------------------- ACTIVCARD_SESSTIMEOUT: 25 # ----------------------------------------------------------------- # ACTIVCARD_SECPOLICY: 0 # This parameter specifies which type of connection will be established # with the ActivEngine: 0(NEGOTIATE), 1(ENCRYPTED), 2(NON-ENCRYPTED). # The ActivEngine client component and its server counterpart can establish # a secure channel based on a Diffie-Hellman key exchange. # ----------------------------------------------------------------- ACTIVCARD_SECPOLICY: 0 # ----------------------------------------------------------------- # ACTIVCARD_PUBKEY: # The ActivEngine Diffie-Hellman public key used to establish a secure channel # between the RADIUS server and the ActivEngine. # # At the time of installation of the ActivEngine, a distribution file called # «aeg.dis» is generated. It contains the information necessary to # establish the connection to the ActivEngine as well as the value of the # public key of the ActivEngine # ----------------------------------------------------------------- ACTIVCARD_PUBKEY: 4807E...get this from the ActivEngine distribution file. radiusd-livingston-2.1/src/0042755000175000017500000000000006734271502013616 5ustar pmpmradiusd-livingston-2.1/src/LICENSE0100644000175000017500000000375506734230227014627 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ radiusd-livingston-2.1/src/Makefile0100644000175000017500000001601206734271442015254 0ustar pmpm# # $Id: Makefile,v 1.9 1999/06/23 23:40:37 cdr Exp $ %Y% Copyright 1991 Livingston Enterprises Inc # # If your system has the /usr/include/shadow.h file and uses getspnam() then # delete the -DNOSHADOW flag from CPPFLAGS in ../build/Makefile.$(EXT) # # To compile with support for SecurID # 1) copy the SecurID header files (SDHEADERS) into this directory # 2) copy the sdiclient.a library from SECURID into $(OBJDIR) # (and run ranlib on it if needed) # 3) make EXT=sun4_4.1 sradiusd # (RS6000_4.1, HP9000_10.01, and sun4_5.5 are also available for sradiusd) # 4) run sradiusd exactly as you would run radiusd # (you can rename it to radiusd if you wish) # # To build on a platform type "make EXT=platform build" where platform # is replaced by the one of the following values. For example, to build # on SunOS 4.1.4 type "make EXT=sun4_4.1 build" # CC = gcc COPT = -O -g CPPFLAGS = -DNOSHADOW LIBS = $(RADLIBS) TARGET=radiusd # EXT= SRCDIR=. OBJDIR=./$(EXT) SLIBS= $(OBJDIR)/sdiclient.a $(OBJDIR)/aegcli.a # use the following defaults to build with iPass support SSL_CFLAGS = -DUSE_SSL SSL_LDFLAGS = # IPINCDIR = /usr/ipass/include # IPLIBDIR = /usr/ipass/lib IPINCDIR = ../ipass/$(EXT)/usr/ipass/include IPLIBDIR = $(OBJDIR) # uncomment rsaref if you're building a USA Domestic binary # SSL_LIBS = -lssl -lcrypto #-lrsaref ILIBS = $(SSL_LIBS) # use the following line for Solaris # ILIBS = -lip $(SSL_LIBS) -lnsl -lsocket # use following for SunOS ILIBS = -lip $(SSL_LIBS) # use this line for BSDI # ILIBS = -lip $(SSL_LIBS) # ILIBS = -lip $(AUTH_LIBS) $(SSL_LIBS) $(IPASS_LIBS) ICFLAGS= $(COPT) $(CPPFLAGS) $(SSL_CFLAGS) -I$(IPINCDIR) $(IPASS_CFLAGS) ILDFLAGS= -L$(IPLIBDIR) $(SSL_LDFLAGS) # # End of iPass configuration. # # comment out next line for BSD/OS 2.1 and 4.0 include $(SRCDIR)/conf/$(EXT) CFLAGS = $(COPT) $(CPPFLAGS) HEADERS = $(SRCDIR)/conf.h $(SRCDIR)/md5.h $(SRCDIR)/radius.h \ $(SRCDIR)/users.h SDHEADERS = $(SRCDIR)/sdacmvls.h $(SRCDIR)/sdconf.h $(SRCDIR)/sdi_athd.h \ $(SRCDIR)/sdi_size.h $(SRCDIR)/sdi_type.h $(SRCDIR)/activcard.h aegapi.h RAD_CSRC = $(SRCDIR)/acct.c \ $(SRCDIR)/dict.c $(SRCDIR)/ipass.c $(SRCDIR)/log.c \ $(SRCDIR)/md5.c $(SRCDIR)/menu.c $(SRCDIR)/pass.c \ $(SRCDIR)/proxy.c $(SRCDIR)/users.c $(SRCDIR)/util.c \ $(SRCDIR)/version.c $(SRCDIR)/radiusd.c $(SRCDIR)/vports.c RAD_OBJS1 = $(OBJDIR)/radiusd.o \ $(OBJDIR)/acct.o $(OBJDIR)/dict.o \ $(OBJDIR)/ipass.o $(OBJDIR)/vports.o \ $(OBJDIR)/log.o $(OBJDIR)/md5.o $(OBJDIR)/menu.o \ $(OBJDIR)/proxy.o $(OBJDIR)/users.o $(OBJDIR)/util.o RAD_OBJS2 = $(OBJDIR)/pass.o $(OBJDIR)/version.o RAD_OBJS = $(RAD_OBJS1) $(RAD_OBJS2) SRAD_OBJS = $(OBJDIR)/sradiusd.o $(OBJDIR)/acct.o $(OBJDIR)/dict.o \ $(OBJDIR)/ipass.o $(OBJDIR)/vports.o \ $(OBJDIR)/log.o $(OBJDIR)/md5.o \ $(OBJDIR)/menu.o $(OBJDIR)/pass.o $(OBJDIR)/proxy.o \ $(OBJDIR)/users.o $(OBJDIR)/util.o \ $(OBJDIR)/securid.o $(OBJDIR)/activcard.o \ $(OBJDIR)/sversion.o IRAD_OBJS = $(OBJDIR)/radiusd.o $(OBJDIR)/acct.o $(OBJDIR)/dict.o \ $(OBJDIR)/iipass.o $(OBJDIR)/vports.o \ $(OBJDIR)/log.o $(OBJDIR)/md5.o \ $(OBJDIR)/menu.o $(OBJDIR)/pass.o $(OBJDIR)/proxy.o \ $(OBJDIR)/users.o $(OBJDIR)/util.o \ $(OBJDIR)/iversion.o TEST_OBJS = $(OBJDIR)/users.o $(OBJDIR)/dict.o \ $(OBJDIR)/util.o $(OBJDIR)/log.o $(OBJDIR)/version.o .PRECIOUS: $(HEADERS) ($SDHEADERS) $(RAD_CSRC) builddbm.c CMDS = $(OBJDIR)/radiusd $(OBJDIR)/builddbm ALLCMDS = $(OBJDIR)/radiusd $(OBJDIR)/builddbm $(OBJDIR)/testuser \ $(OBJDIR)/dbmkeys $(OBJDIR)/dbmrec $(OBJDIR)/radtest \ $(OBJDIR)/md5test build: $(OBJDIR) $(CMDS) all: $(OBJDIR) $(ALLCMDS) clean: -rm -f $(ALLCMDS) -rm -f $(OBJDIR)/*.o clobber: clean sccs clean strip: strip $(CMDS) allstrip: strip $(ALLCMDS) b: $(OBJDIR)/builddbm i: $(OBJDIR)/iradiusd m: $(OBJDIR)/md5test r: $(OBJDIR)/radiusd s: $(OBJDIR)/sradiusd t: $(OBJDIR)/radtest $(OBJDIR): - mkdir -p $(OBJDIR) $(OBJDIR)/radiusd: $(RAD_OBJS) $(CC) $(CFLAGS) -o $@ $(RAD_OBJS) $(LIBS) $(OBJDIR)/builddbm: $(OBJDIR)/builddbm.o $(OBJDIR)/version.o $(OBJDIR)/log.o $(HEADERS) $(CC) $(CFLAGS) -o $@ $(OBJDIR)/builddbm.o $(OBJDIR)/version.o $(OBJDIR)/log.o $(LIBS) $(OBJDIR)/md5test: $(SRCDIR)/md5test.c $(HEADERS) $(OBJDIR)/md5.o $(CC) $(CFLAGS) -o $@ $(SRCDIR)/md5test.c $(OBJDIR)/md5.o $(OBJDIR)/radtest: $(SRCDIR)/radtest.c $(HEADERS) $(OBJDIR)/md5.o $(OBJDIR)/dict.o $(OBJDIR)/util.o $(OBJDIR)/log.o $(CC) $(CFLAGS) -o $@ $(SRCDIR)/radtest.c $(OBJDIR)/md5.o $(OBJDIR)/dict.o $(OBJDIR)/util.o $(OBJDIR)/log.o $(LIBS) $(OBJDIR)/testuser: $(SRCDIR)/testuser.c $(HEADERS) $(TEST_OBJS) $(CC) $(CFLAGS) -o $@ $(SRCDIR)/testuser.c $(TEST_OBJS) $(LIBS) $(OBJDIR)/dbmkeys: $(SRCDIR)/dbmkeys.c $(CC) $(CFLAGS) -o $@ $(SRCDIR)/dbmkeys.c $(LIBS) $(OBJDIR)/dbmrec: $(SRCDIR)/dbmrec.c $(HEADERS) $(TEST_OBJS) $(CC) $(CFLAGS) -o $@ $(SRCDIR)/dbmrec.c $(TEST_OBJS) $(LIBS) $(OBJDIR)/builddbm.o: $(SRCDIR)/builddbm.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/builddbm.c $(OBJDIR)/radiusd.o: $(SRCDIR)/radiusd.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/radiusd.c $(OBJDIR)/users.o: $(SRCDIR)/users.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/users.c $(OBJDIR)/dict.o: $(SRCDIR)/dict.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/dict.c $(OBJDIR)/util.o: $(SRCDIR)/util.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/util.c $(OBJDIR)/md5.o: $(SRCDIR)/md5.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/md5.c $(OBJDIR)/acct.o: $(SRCDIR)/acct.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/acct.c $(OBJDIR)/version.o: $(SRCDIR)/version.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/version.c $(OBJDIR)/menu.o: $(SRCDIR)/menu.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/menu.c $(OBJDIR)/log.o: $(SRCDIR)/log.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/log.c $(OBJDIR)/proxy.o: $(SRCDIR)/proxy.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/proxy.c $(OBJDIR)/ipass.o: $(SRCDIR)/ipass.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/ipass.c $(OBJDIR)/pass.o: $(SRCDIR)/pass.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/pass.c $(OBJDIR)/vports.o: $(SRCDIR)/vports.c $(CC) -c -o $@ $(CFLAGS) $(SRCDIR)/vports.c # # SecurID and Activcard support # sradiusd: $(OBJDIR)/sradiusd $(OBJDIR)/sradiusd: $(SRAD_OBJS) $(CC) $(CFLAGS) -o $@ $(SRAD_OBJS) $(SLIBS) $(LIBS) $(OBJDIR)/securid.o: $(SRCDIR)/securid.c $(SDHEADERS) $(CC) -c -o $@ $(CFLAGS) -DSECURID -DACTIVCARD $(SRCDIR)/securid.c $(OBJDIR)/sversion.o: $(SRCDIR)/version.c $(CC) -c -o $@ -DSECURID -DACTIVCARD $(CFLAGS) $(SRCDIR)/version.c $(OBJDIR)/sradiusd.o: $(SRCDIR)/radiusd.c $(SDHEADERS) $(CC) -c -o $@ $(CFLAGS) -DSECURID -DACTIVCARD $(SRCDIR)/radiusd.c # $(OBJDIR)/activcard.o: $(SRCDIR)/activcard.c $(SDHEADERS) $(CC) -c -o $@ $(CFLAGS) -DSECURID -DACTIVCARD $(SRCDIR)/activcard.c # # Ipass support # iradiusd: $(OBJDIR)/iradiusd $(OBJDIR)/iradiusd: $(IRAD_OBJS) $(CC) $(ILDFLAGS) -o $@ $(IRAD_OBJS) $(ILIBS) $(OBJDIR)/iipass.o: $(SRCDIR)/ipass.c $(CC) -c -o $@ $(ICFLAGS) -DIPASS $(SRCDIR)/ipass.c $(OBJDIR)/iversion.o: $(SRCDIR)/version.c $(CC) -c -o $@ $(ICFLAGS) -DIPASS $(SRCDIR)/version.c radiusd-livingston-2.1/src/acct.c0100644000175000017500000002423406734270165014700 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: acct.c,v 1.16 1999/06/23 23:40:37 cdr Exp $ Copyright 1994-1999 Lucent Technologies, Inc."; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" #define SIGN_NOCLIENT -1 #define SIGN_MATCH 0 #define SIGN_ZERO 1 /* only returned if accept_zero is set */ #define SIGN_NOMATCH 2 extern char recv_buffer[4096]; extern char send_buffer[4096]; extern char *progname; extern int debug_flag; extern int accept_zero; #ifdef VPORTS extern int vports_flag; #endif extern char *radacct_dir; extern char *radius_dir; extern UINT4 expiration_seconds; extern UINT4 warning_seconds; extern int errno; extern struct sockaddr_in rad_saremote; void rad_acctreq(fd) int fd; { AUTH_REQ *authreq; AUTH_REQ *radrecv(); UINT4 addr; char *ip_hostname(); char *ipaddr2strp(); char secret[20]; int calc_acctreq(); int handle_proxy(); int logok; int proxied; int rad_accounting(); int recfrom(); int retsig; int result; size_t salen; struct sockaddr_in *sin; u_short port; time_t time(); void hexdump(); void reqfree(); void send_acct_reply(); void vp_update_cid(); salen = sizeof(rad_saremote); sin = (struct sockaddr_in *) & rad_saremote; result = recvfrom (fd, (char *) recv_buffer, (int) sizeof(recv_buffer), (int) 0, (struct sockaddr *)&rad_saremote, &salen); if (result < AUTH_HDR_LEN) { log_err("accounting: runt packet of %d bytes\n",result); return; } addr = ntohl(sin->sin_addr.s_addr); port = ntohs(sin->sin_port); /* Verify the client -- returns shared secret in secret */ retsig=calc_acctreq(addr,secret,recv_buffer,result); /* To be strictly compliant with the RADIUS Accounting RFC we only accept packets that returned SIGN_MATCH to indicate the Request-Authenticator is valid. This requires ComOS 3.3.1 or later. If accept_flag is set then we also accept all-zero Request-Authenticator. */ if (retsig == SIGN_NOCLIENT) { /* We do not respond when this fails */ log_err("accounting: unknown client %s/%d ignored\n", ipaddr2strp(addr),port); return; } else if (retsig == SIGN_NOMATCH) { log_err("accounting: client %s/%d sent accounting-request with invalid request authenticator\n",ipaddr2strp(addr),port); if (debug_flag > 2) { hexdump(recv_buffer, result); } return; } authreq = radrecv( addr, port, secret, recv_buffer, result ); if (authreq == (AUTH_REQ *)NULL) { return; } /* log it locally */ logok = rad_accounting(authreq,retsig); /* handle_proxy returns 1 if it forwarded the packet, 0 if it did not forward the packet, and -1 if there was an error */ proxied = handle_proxy(authreq); if (authreq->flags & REQ_ERR) { reqfree(authreq,"rad_acctreq"); return; } /* If we did not forward this to a remote server, we now let NAS know it is OK to delete from buffer If we did forward it to a proxy server, we will notify NAS to delete when we get the ack back from the remote server. This means it may wind up in our own logs multiple times, but that is useful to know */ if (proxied == 0) { if (logok == 1) { send_acct_reply(authreq, (VALUE_PAIR *)NULL, fd); } reqfree(authreq,"rad_acctreq"); } if (proxied == 1 && (authreq->flags & REQ_FREE)) { reqfree(authreq,"rad_acctreq"); } return; } int rad_accounting(authreq,sign) AUTH_REQ *authreq; int sign; { FILE *outfd; char buffer[512]; char *client_hostname(); char clientname[MAX_HOST_SIZE]; char *ctime(); VALUE_PAIR *pair; time_t curtime; time_t time(); int fclose(); int fputs(); void fprint_attr_val(); #ifdef VPORTS void vp_update_cid(); #endif if (authreq == (AUTH_REQ *)NULL) { return 0; } #ifdef VPORTS if (vports_flag == 1) { vp_update_cid(authreq); } #endif /* VPORTS */ strncpy(clientname, client_hostname(authreq->ipaddr), MAX_HOST_SIZE); /* * Create a directory for this client. */ sprintf(buffer, "%s/%s", radacct_dir, clientname); mkdir(buffer, (mode_t) 0755); /* * Write Detail file. */ sprintf(buffer, "%s/%s/detail", radacct_dir, clientname); if((outfd = fopen(buffer, "a")) == (FILE *)NULL) { log_err("accounting: could not append to file %s\n", buffer); /* do not respond if we cannot save record */ return 0; } /* Post a timestamp */ curtime = time(0); fputs(ctime(&curtime), outfd); /* Write each attribute/value to the log file */ pair = authreq->request; while(pair != (VALUE_PAIR *)NULL) { if (pair->attribute != PW_PROXY) { fputs("\t", outfd); fprint_attr_val(outfd, pair); fputs("\n", outfd); } pair = pair->next; } /* print the seconds since epoch for easier processing */ sprintf(buffer,"\tTimestamp = %ld\n",(long)curtime); fputs(buffer,outfd); if (sign == SIGN_ZERO) { fputs("\tRequest-Authenticator = None\n",outfd); } fputs("\n", outfd); fclose(outfd); return 1; } /************************************************************************* * * Function: send_acct_reply * * Purpose: Reply to the request with an ACKNOWLEDGE. Also attach * reply attribute value pairs (not that there should be any) * *************************************************************************/ void send_acct_reply(authreq, reply, activefd) AUTH_REQ *authreq; VALUE_PAIR *reply; int activefd; { extern int report[]; char *req2strp(); int total_length; int build_packet(); void send_packet(); DEBUG("sending acct-response to %s\n", req2strp(authreq)); total_length = build_packet(authreq,reply,(char *)NULL,PW_ACCOUNTING_RESPONSE,FW_REPLY,send_buffer); send_packet(activefd,authreq->ipaddr,authreq->udp_port, send_buffer,total_length); report[RR_ACCOUNT]++; } /************************************************************************* * * Function: calc_acctreq * * Purpose: Validates the requesting client NAS. Calculates * the accounting-request signature based on the * client's private key. * Returns: -1 Client not found * 0 signature matched expected value * 1 signature was all-zero and accept_zero flag is true * 2 signature was non-zero and did not match * *************************************************************************/ int calc_acctreq(client,secret,buffer,buflen) UINT4 client; char *secret; u_char *buffer; int buflen; { extern int accept_zero; AUTH_HDR *auth; u_char digest[AUTH_VECTOR_LEN]; u_char savedigest[AUTH_VECTOR_LEN]; char hostnm[256]; int secretlen; int len; int find_client(); void md5_calc(); /* * Validate the requesting IP address - * Not secure, but worth the check for accidental requests * find_client() logs an error message if needed */ if(find_client(client, secret, hostnm) != 0) { return(SIGN_NOCLIENT); } /* * The NAS and RADIUS accounting server share a secret. * The Request Authenticator field in Accounting-Request packets * contains a one-way MD5 hash calculated over a stream of octets * consisting of the Code + Identifier + Length + 16 zero octets + * request attributes + shared secret (where + indicates * concatenation). The 16 octet MD5 hash value is stored in the * Authenticator field of the Accounting-Request packet. */ auth = (AUTH_HDR *)buffer; memset(savedigest, 0, AUTH_VECTOR_LEN); if (accept_zero && memcmp(savedigest,auth->vector,AUTH_VECTOR_LEN) == 0) { return(SIGN_ZERO); } len = ntohs(auth->length); memcpy(savedigest,auth->vector,AUTH_VECTOR_LEN); memset(auth->vector, 0, AUTH_VECTOR_LEN); secretlen = strlen((char *)secret); memcpy(buffer+len,secret,secretlen); md5_calc(digest, buffer, len+secretlen); memcpy(auth->vector,savedigest,AUTH_VECTOR_LEN); memset(buffer+len,0,secretlen); if (memcmp(digest,savedigest,AUTH_VECTOR_LEN) == 0) { return(SIGN_MATCH); } else { return(SIGN_NOMATCH); } /* secret is returned as a side-effect */ } radiusd-livingston-2.1/src/activcard.c0100644000175000017500000002054406577133273015731 0ustar pmpm/* * Copyright (C) ActivCard 1996-1997. * * Module : activcard.c * Purpose: ActivEngine API * Version: 2.0.1.4 F9706F */ /* * * ActivCard, Inc. * 303 Twin Dolphin Drive, Suite 420 * Redwood City, CA 94065 * www.activcard.com * * Copyright (C) ActivCard 1996-1997. * * This software is provided by Lucent Technologies Remote Access under license from ActivCard, Inc., * * ActivCard, Inc. makes no representations or warranties with * respect to the contents or use of this software, and specifically * disclaims any express or implied warranties of merchantability or * fitness for any particular purpose. Further, ActivCard reserves the * right to revise this software and to make changes to its content, * at any time, without obligation to notify any person or entity of * such revisions or changes. * */ #include #include #include #include #include #include #include #include #include #include #include "radius.h" #include "aegapi.h" #include "activcard.h" /* globals */ unsigned long ac_session; char ac_challenge[AUTH_PASS_LEN]; void activcard_strip(ptr) char *ptr; { int nspaces; nspaces = 0; while(*ptr) { while(isspace(*(ptr+nspaces))) nspaces++; *ptr = *(ptr+nspaces); ptr++; } } int activcard_getpair(line, in_attr, in_val) char *line, **in_attr, **in_val; { static char attr[BUFSIZ], val[BUFSIZ]; char *ptr; *in_attr = attr; *in_val = val; /* initialize containers for attribute pair*/ memset(attr, '\0', sizeof(attr)); memset(val , '\0', sizeof(val)); /* copy this token into the attribute field */ while(isspace(*line)) line++; /* get read of leading spaces */ if(*line == '#') return(-1); /* comment line */ ptr = attr; while(isgraph(*line) && *line != ':' && *line != '#') *ptr++=*line++; /* next token should be an equal sign, strip spaces */ while(isspace(*line)) line++; if(*line != ':') return(-1); line++; /* go on */ /* next token should be the attribute value */ while(isspace(*line)) line++; /* get read of leading spaces */ ptr = val; while(isgraph(*line) && *line != '#') *ptr++=*line++; /* ignore any thing else */ return(0); } int activcard_readcnf(config_file, ac_cnf) char *config_file; /* configuration file */ struct ac_config *ac_cnf; /* primary aeg server */ { FILE *fd; char buffer[BUFSIZ]; char *attr, *val; char port[10+1], timeout[10+1]; /* initialize */ memset(ac_cnf, '\0', sizeof(struct ac_config)); memset(port, '\0', sizeof(port)); memset(timeout, '\0', sizeof(timeout)); ac_session = -1; /* open activcard configuration file */ if((fd = fopen(config_file, "r")) == NULL) { log_err("activcard_readcnf: could not open config file %s\n", \ config_file); return(-1); } while(fgets(buffer, sizeof(buffer)-1, fd)) { if(activcard_getpair(buffer, &attr, &val)) continue; /* not pair */ if(!strcmp(attr, ACTIVCARD_APPLICATION)) { strcpy(ac_cnf->application, val); } else if(!strcmp(attr, ACTIVCARD_CHALLENGE)) { strcpy(ac_challenge, val); } else if(!strcmp(attr, ACTIVCARD_HOST)) { strcpy(ac_cnf->connection, val); strcat(ac_cnf->connection, "/"); } else if(!strcmp(attr, ACTIVCARD_PUBKEY)) { strcpy(ac_cnf->public, val); } else if(!strcmp(attr, ACTIVCARD_AUTHPORT)) { strcpy(port, val); } else if(!strcmp(attr, ACTIVCARD_SESSTIMEOUT)) { strcpy(timeout, val); } else if(!strcmp(attr, ACTIVCARD_SECPOLICY)) { ac_cnf->policy = (aegFlagSecure )atoi(val); } } fclose(fd); /* finish connection string to open the session */ if(ac_cnf->connection[0] != '\0') { /* aeg host */ strcat(ac_cnf->connection, port); strcat(ac_cnf->connection, "/"); strcat(ac_cnf->connection, timeout); } else { log_err("activcard_readcnf: bad configuration file %s\n", config_file); return(-1); } return(0); } int activcard_init() { extern char *radius_dir; int result; char config_file[BUFSIZ]; struct ac_config ac_cnf; /* path to configuration file, we follow radius_dir */ sprintf(config_file, "%s/%s", radius_dir, ACTIVCARD_CONFIG); /* check configuration file for activcard support */ if(access(config_file, F_OK)) { DEBUG("activcard_init: activcard support not configured\n"); return(0); } /* read configuration file at this point */ if(activcard_readcnf(config_file, &ac_cnf) != 0) { log_err("activcard_init: error reading configuration file\n"); return(-1); } /* open activcard session */ result = aeg_open_session_ex(&ac_session, ac_cnf.connection, \ ac_cnf.public, ac_cnf.application, ac_cnf.policy); if (result != AEG_SERVICE_SUCCEEDED) { ac_session = -1; log_err("activcard_init: aeg_open_session_ex error %d\n", result); log_err("activcard_init: activcard support disabled\n"); return(-1); } else { DEBUG("activcard_init: opened session %d (%s) to "\ "%s (policy %d)\n", ac_session, ac_cnf.application, \ ac_cnf.connection, ac_cnf.policy); } return(0); } int activcard_auth(auth_name, password, authreq, user_reply, activefd) char *auth_name; char *password; AUTH_REQ *authreq; VALUE_PAIR *user_reply; int activefd; { aeIdentity userId; aeAuthMode method; VALUE_PAIR *namepair, *get_attribute(); int result; char chall[CHALLENGE_SIZE], *pfr, *pto; char msg[128], state_value[128]; int response, challenge; void pairfree(), reqfree(), send_accept(), send_challenge(); void send_reject(); /* initialize... */ memset(msg, '\0', sizeof(msg)); userId.Type = LOGIN_NAME_TYPE; userId.pVal = auth_name; response = -1; /* get the state */ namepair = get_attribute(authreq->request, PW_STATE); if(namepair == (VALUE_PAIR *)NULL) { /* first time arround */ DEBUG("activcard_auth: authenticating user %s\n", auth_name); /* authentication mode */ result = aeg_get_security_param(ac_session, &userId, \ AEG_AUTH_MODE_PARAM, &method); if(result != AEG_SERVICE_SUCCEEDED) { log_err("activcard_auth: aeg_get_security_param error %d\n", \ result); response = -1; } else if( !strcmp(ac_challenge, password) ) { switch(method) { case ASYNCHRONOUS_MODE: case DUAL_AUTH_MODE: memset(chall, '\0', sizeof(chall)); result = \ aeg_get_async_auth_challenge(ac_session, &userId, chall); if(result != AEG_SERVICE_SUCCEEDED) { log_err("activcard_auth: aeg_get_async_auth_challenge "\ "error %d\n", result); response = -1; } else { response = 1; } break; /* async mode not allowed, falls here */ case SYNCHRONOUS_MODE: default: log_err("activcard_auth: bad authentication mode %d "\ "(sync).\n", method); response = -1; } } else { switch(method) { case SYNCHRONOUS_MODE: case DUAL_AUTH_MODE: result=aeg_check_sync_auth_code(ac_session, &userId, password); if(result != AEG_SERVICE_SUCCEEDED) { response = -1; } else { response = 0; } break; /* sync mode not allowed, falls here */ case ASYNCHRONOUS_MODE: default: log_err("activcard_auth: bad authentication mode %d "\ "(async).\n", method); response = -1; } } } else { /* response to challenge */ /* strip any spaces in the response */ activcard_strip(password); DEBUG("activcard_auth: response to challenge %s for %s\n", password, auth_name); memset(chall, '\0', sizeof(chall)); pfr = namepair->strvalue+10; pto = chall; while(isdigit(*pfr)) *pto++ = *pfr++; result = aeg_check_async_auth_code (ac_session, &userId,\ chall, password); if(result != AEG_SERVICE_SUCCEEDED) { response = -1; } else { response = 0; } } /* send response accordingly */ switch(response) { case 0: send_accept(authreq, user_reply, (char *)NULL, activefd); challenge = 0; break; case 1: sprintf(msg, \ "\nChallenge/Response Authentication requested...\n" "\rChallenge: %s\n\rResponse: ", chall); sprintf(state_value, "ACTIVCARD_%s=%u", chall, getpid()); send_challenge(authreq, msg, state_value, activefd); challenge = 1; break; case -1: send_reject(authreq, (char *)NULL, activefd); challenge = 0; break; } reqfree(authreq,"activcard_auth"); pairfree(user_reply,"activcard_auth"); return(challenge); } void activcard_exit() { if(ac_session != -1) { /* do we have a session opened */ aeg_close_session(ac_session); /* close activcard session */ DEBUG("activcard_exit: closed session %d\n", ac_session); } } radiusd-livingston-2.1/src/activcard.h0100644000175000017500000000130206425601520015710 0ustar pmpm/* * Copyright (C) ActivCard 1996-1997. * * Module : activcard.h * Purpose: ActivEngine API * Version: 2.0.1.4 F9706F */ /* used to store configuration parameters */ struct ac_config { char application[APPLICATION_ID_SIZE]; char connection[AEG_MAX_SERVERNAME_LEN]; char public[PUBLIC_KEY_SIZE]; aegFlagSecure policy; }; #define ACTIVCARD_APPLICATION "ACTIVCARD_APPLICATION" #define ACTIVCARD_CHALLENGE "ACTIVCARD_CHALLENGE" #define ACTIVCARD_HOST "ACTIVCARD_HOST" #define ACTIVCARD_PUBKEY "ACTIVCARD_PUBKEY" #define ACTIVCARD_AUTHPORT "ACTIVCARD_AUTHPORT" #define ACTIVCARD_SESSTIMEOUT "ACTIVCARD_SESSTIMEOUT" #define ACTIVCARD_SECPOLICY "ACTIVCARD_SECPOLICY" radiusd-livingston-2.1/src/aegapi.h0100644000175000017500000002323206577133022015211 0ustar pmpm/* * Copyright (C) ActivCard 1996-1997. * * Module : aeg/inc/aegapi.h * Purpose: ActivEngine Security Services API public header file * Version: 2.0.1.4 F9706F */ /* * * ActivCard, Inc. * 303 Twin Dolphin Drive, Suite 420 * Redwood City, CA 94065 * www.activcard.com * * Copyright (C) ActivCard 1996-1997. * * This software is provided by Lucent Remote Access under license from ActivCard, Inc., * * ActivCard, Inc. makes no representations or warranties with * respect to the contents or use of this software, and specifically * disclaims any express or implied warranties of merchantability or * fitness for any particular purpose. Further, ActivCard reserves the * right to revise this software and to make changes to its content, * at any time, without obligation to notify any person or entity of * such revisions or changes. * */ #ifndef _AEGAPI_H_ #define _AEGAPI_H_ #ifdef __cplusplus extern "C" { #endif /* * Macros, defines, constants, ... * =============================== */ /*---------------------- Value definitions ---------------------------- */ #define IDENTITY_SIZE (25+1) #define APPLICATION_ID_SIZE (20+1) #define CHALLENGE_SIZE (8+1) #define CODE_SIZE (16+1) #define SECRET_VALUE_SIZE (16+1) #define PUBLIC_KEY_SIZE (256+1) #define AEG_MAX_CERTIFICATE_LENGTH CODE_SIZE #define AEG_MAX_CERTDATA_LENGTH 8192 #define AEG_MAJOR_VERSION(x) ((int)(((unsigned long)(x) >> 24) & 0xFF)) #define AEG_MINOR_VERSION(x) ((int)(((unsigned long)(x) >> 16) & 0xFF)) #define AEG_BUILD_VERSION(x) ((int)(((unsigned long)(x) >> 8) & 0xFF)) /*---------------------- Identity Type ------------------------------ */ typedef enum { SERIAL_NUMBER_TYPE, /* SerialNumber Type */ LOGIN_NAME_TYPE /* LoginName Type */ } aeIdentityType; /*----------------- Identity Code definitions ------------------------- */ typedef struct { aeIdentityType Type; /* LoginNameType or SerialNumberType */ char *pVal; } aeIdentity; /*------------------------- Return Value ------------------------------ */ typedef enum { AEG_ERR_NO_ERROR = 0, /* No Error */ AEG_ERR_INTERNAL_ERROR = 1, /* Internal parser error: should not happen */ AEG_ERR_UNKNOWN_SESSION_ID = 10,/* Wrong session identifier */ AEG_ERR_UNKNOWN_APPLICATION = 11,/* Unknown application name or * application not available for * the token */ AEG_ERR_UNKNOWN_IDENTITY = 12, /* Unknown identity, either the serial number or * the login name is wrong */ AEG_ERR_INVALID_DIRECTIVE = 13, AEG_ERR_ACCESS_TO_SERVICE_DENIED = 14,/* Access to service denied or service not * available for the user */ AEG_ERR_AUTH_CODE_CHECK_FAILED = 15,/* Authentication failed */ AEG_ERR_INVALID_CHALLENGE = 16, /* Challenge not valid */ AEG_ERR_INVALID_AUTH_CODE = 17, /* Authentication code not valid */ AEG_ERR_BAD_PARAM = 18, /* One of the parameter is NULL or invalid */ AEG_ERR_MEMORY_CLIENT = 19, /* Out of memory (in the client API) */ AEG_ERR_MEMORY_SERVER = 20, /* Out of memory (in the server) */ AEG_ERR_SERVER_BUSY = 21, /* Server busy */ AEG_ERR_SLAVEMODE = 22, /* The Server is in slave mode, and the service * requested is not allowed in slave mode */ AEG_ERR_OBJECT_ALREADY_EXIST = 23, /* cannot add a database object (application user...) * that already exists in the database * Should not happen in this API */ AEG_ERR_OBJECT_NOT_FOUND = 24, /* Should not happen in this API */ AEG_ERR_INVALID_CHARACTER = 25, /* Should not happen in this API */ AEG_ERR_SECURE_CLIENT_FAILED = 100,/* Crypto negociation failure (client side) */ AEG_ERR_SECURE_SERVER_FAILED = 101,/* Crypto negociation failure (server side) */ AEG_ERR_SECURE_BAD_MAC = 102, /* Invalid MAC */ AEG_ERR_SECURE_WRONG_DH_PUBLIC = 103,/* Wrong ActivEngine server Diffie-Hellman public value */ /* Network subsystem not ready or incompatible or bad configuration */ /* Not enough memory or network resource (file descriptor, buffer) */ /* Network subsystem general failure */ /* The read/write packet format is not correct */ AEG_ERR_NETWORK_FAILURE = 200, AEG_ERR_NETWORK_BROKENPIPE = 201,/* Connection lost */ /* Invalid IP Adress or port number */ /* Unable to connect to given host, or failure during connection */ AEG_ERR_NETWORK_CONNECT = 202, /* Network timeout */ AEG_ERR_NETWORK_TIMEOUT = 203, /* Service not implemented in this version */ AEG_ERR_NOTIMPLEMENTED = 204 } aeErrorCode; #define AEG_SERVICE_SUCCEEDED AEG_ERR_NO_ERROR #define AEG_ERR_BAD_CERTIF_CODE AEG_ERR_AUTH_CODE_CHECK_FAILED /*----------------- DirAuthMode Code definitions ---------------------- */ typedef enum { ASYNCHRONOUS_MODE, SYNCHRONOUS_MODE, DUAL_AUTH_MODE } aeAuthMode; #ifndef _ADMAPI_H_ typedef enum { AEG_SECURE_ALL, /* the API is completely free to negociate whatever protocol it wants down to the no encryption protocol if the server does not support anything better */ AEG_SECURE_ENCRYPTED_ONLY, /* If the target server does not support encryption, the connection will fails with an AEG_SECURE_NEGOCIATION_FAILED error.*/ AEG_SECURE_NOENCRYPTED_ONLY /* A non encrypted protocol is mandatory. If the server does not support a non secure channel an AEG_SECURE_NEGOCIATION_FAILED error will be returned. */ } aegFlagSecure; #endif typedef enum { AEG_INFO_SERVERNAME, AEG_INFO_SERVERIPADD, AEG_INFO_CNXTIMEOUT, AEG_INFO_ENCRYPTION, AEG_INFO_VERSION_AEG, AEG_INFO_VERSION_API } aegInfo; #define AEG_MAX_SERVERNAME_LEN 65 #define AEG_ENCRYPTION_OFF 0 #define AEG_ENCRYPTION_ON 1 /* ---------------- Certification definitions -------- */ typedef enum { AEG_CERT_DATA_FIELD, AEG_CERT_DATA_BUFFER } aegCertifDataType; /*----------------- get security param definitions ------------------------ */ typedef enum { AEG_CERTIFICATION_PARAM, AEG_VERIF_AFTER_AUTH_PARAM, AEG_AUTH_MODE_PARAM } aegSecurityType; #define CERTIF_MODE_NONE 0 #define CERTIF_MODE_ASYNCHRONOUS 1 #define CERTIF_MODE_SYNCHRONOUS 2 typedef struct aeCertifDataTAG { int len_min[5]; int len_max[5]; int period_options[5]; int mode; /* 0=none, 1=Async mode, 2=Sync mode */ int flag_verif; /* Server authentication after certification (1) or not (0) */ } aeCertifData; /*----------------- Application Id definitions ------------------------ */ int aeg_open_session_ex ( #if defined(__STDC__) unsigned long *SessionId, const char *AEGServerId, const char *AEGPublicKey, const char *ApplicationId, aegFlagSecure AEGSecureFlag #endif /* __STDC__ */ ); int aeg_close_session ( #if defined(__STDC__) unsigned long SessionId #endif /* __STDC__ */ ); int aeg_get_security_param ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity *Identity, aegSecurityType InfoType, void *Info #endif /* __STDC__ */ ); int aeg_get_info ( #if defined(__STDC__) unsigned long SessionId, aegInfo keyword, void *pResult #endif /* __STDC__ */ ); int aeg_get_async_auth_challenge ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity * Identity, char *Challenge #endif /* __STDC__ */ ); int aeg_check_async_auth_code ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity * Identity, const char *Challenge, const char *Code #endif /* __STDC__ */ ); int aeg_check_sync_auth_code ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity * Identity, const char *Code #endif /* __STDC__ */ ); int aeg_get_challenge_secret_value ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity * Identity, char *Challenge #endif /* __STDC__ */ ); int aeg_extract_secret_value ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity * Identity, const char *Challenge, const char *Code, char *SecretValue #endif /* __STDC__ */ ); int aeg_check_certificate( #if defined(__STDC__) unsigned long SessionId, const aeIdentity *Identity, char *Certificate, char *Data, aegCertifDataType DataType, int DataLen #endif /* __STDC__ */ ); int aeg_get_server_auth_code( #if defined(__STDC__) unsigned long SessionId, const aeIdentity *Identity, char *Challenge, char * ServerAuthCode #endif /* __STDC__ */ ); /* --------------------------------------------------------- */ int aeg_open_session ( #if defined(__STDC__) unsigned long *SessionId, const char *ApplicationId, const char *ApplicationPrivateKey, const char *AEGServerId, const char *AEGPublicKey #endif /* __STDC__ */ ); int aeg_get_client_api_version ( #if defined(__STDC__) unsigned long SessionId, unsigned long *VersionNumber #endif /* __STDC__ */ ); int aeg_get_server_version ( #if defined(__STDC__) unsigned long SessionId, unsigned long *VersionNumber #endif /* __STDC__ */ ); int aeg_get_auth_mode ( #if defined(__STDC__) unsigned long SessionId, const aeIdentity * Identity, aeAuthMode * DirAuthMode #endif /* __STDC__ */ ); /* --------------------------------------------------------- */ #ifdef __cplusplus } #endif #endif /* _AEGAPI_H_ */ radiusd-livingston-2.1/src/builddbm.c0100644000175000017500000002330306734270166015545 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: builddbm.c,v 1.19 1999/06/23 23:40:38 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" #if defined(NDBM) # include # include #else /* not NDBM */ # include #endif /* NDBM */ extern int errno; char *progname; char *radius_dir; char *radius_log; int debug_flag = 0; int radius_dbm = 1; /* needed for version() */ int accept_zero = 0; #define FIND_MODE_NAME 0 #define FIND_MODE_REPLY 1 #define FIND_MODE_SKIP 2 #define FIND_MODE_FLUSH 3 FILE *userfd; int default_count; /* number of DEFAULT entries found */ int linenum; /* line in users file, for error messages */ int lineuser; /* line current user started on, for error messages */ int main(argc,argv) int argc; char **argv; { char argval; char content[1024]; char name[128]; datum contentd; datum named; int chdir(); int errcount; /* number of users not stored, usually dups */ int usercount; /* number of users stored */ #ifdef NDBM DBM *db; int xx; #else /* not NDBM */ int fd; #endif /* NDBM */ int user_read(); void usage(); void version(); /* Parse arguments */ progname = *argv++; argc--; radius_dir = "."; /* default looks in current directory */ while(argc) { if(**argv != '-') { usage(); } argval = *(*argv + 1); argc--; argv++; switch(argval) { case 'd': if(argc == 0) { usage(); } radius_dir = *argv; argc--; argv++; break; case 'h': usage(); break; case 'l': /* change logging from syslog */ if(argc == 0) { usage(); } radius_log = *argv; argc--; argv++; break; case 'v': version(); break; case 'x': debug_flag = 1; break; default: usage(); break; } } if (debug_flag) { if (radius_log == (char *)NULL) { /* * for backward compatibility * send messages to users tty */ radius_log = "/dev/tty"; } else if (strcmp(radius_log, "syslog") == 0) { /* * allow user to override backward compatibility * and send debug to syslog */ radius_log = (char *)NULL; } } /* Open Database */ errno = 0; if (chdir(radius_dir) < 0) { fprintf(stderr, "%s: unable to change to directory %s - %s\n",progname,radius_dir,sys_errlist[errno]); exit(-1); } #ifdef NDBM errno = 0; if((db = dbm_open("users", O_RDWR | O_CREAT | O_TRUNC, 0600)) == (DBM *)NULL) { fprintf(stderr, "%s: dbm_open failed - %s\n", progname, sys_errlist[errno]); exit(-1); } #else /* not NDBM */ errno = 0; if((fd = open("users.pag", O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { fprintf(stderr,"%s: Couldn't open users.pag for writing - %s\n",progname,sys_errlist[errno]); exit(-1); } close(fd); errno = 0; if((fd = open("users.dir", O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { fprintf(stderr,"%s: Couldn't open users.dir for writing - %s\n",progname,sys_errlist[errno]); exit(-1); } close(fd); errno = 0; if(dbminit("users") != 0) { fprintf(stderr, "%s: dbminit failed - %s\n",progname, sys_errlist[errno]); exit(-1); } #endif /* not NDBM */ /* read through users file putting entries into database */ default_count = 0; errcount = 0; usercount = 0; while(user_read(name, content) == 0) { named.dptr = name; named.dsize = strlen(name); contentd.dptr = content; contentd.dsize = strlen(content); #ifdef NDBM if((xx = dbm_store(db, named, contentd, DBM_INSERT)) != 0) #else /* not NDBM */ if(store(named, contentd) != 0) #endif /* not NDBM */ { fprintf(stderr, "%s: could not store %s from line %d, check for duplicate\n", progname,name,lineuser); errcount++; } else { usercount++; } } #ifdef NDBM dbm_close(db); #else /* not NDBM */ dbmclose(); #endif /* not NDBM */ /* report results */ printf("%s: %d user%s stored in DBM file",progname,usercount,usercount==1?"":"s"); if (default_count > 0) { printf(" including %d DEFAULT entries\n",default_count); } else { printf("\n"); } if (errcount > 0) { printf("%s: %d user%s not written to DBM file, check for duplicates\n",progname,errcount,errcount==1?"":"s"); } exit(0); } /************************************************************************* * * Function: user_read * * Purpose: Return each user in the database - name is key content * is 2 strings - check values, and reply values seperated * by a newline. * *************************************************************************/ int user_read(name, content) char *name; char *content; { extern int linenum; extern int lineuser; static char buffer[256]; char *ptr; int mode; char *base_name = name; /* * Open the user table */ if(userfd == (FILE *)NULL) { if((userfd = fopen(RADIUS_USERS, "r")) == (FILE *)NULL) { fprintf(stderr, "%s: could not open %s for reading\n", progname, buffer); exit(-1); } linenum = 0; *buffer = '\0'; } mode = FIND_MODE_NAME; while(*buffer || (fgets(buffer, sizeof(buffer), userfd) != (char *)NULL)) { linenum++; /* track line number for error messages */ /* skip comments */ if (*buffer == '#') { *buffer = '\0'; continue; } if(mode == FIND_MODE_NAME) { /* * Find the entry starting with the users name */ if(*buffer != '\t' && *buffer != ' ' && *buffer != '\n' && *buffer != '\r') { ptr = buffer; while(*ptr != ' ' && *ptr != '\t' && *ptr != '\0') { *name++ = *ptr++; } *name = '\0'; if(*ptr == '\0') { continue; } if (strncmp(base_name, "DEFAULT",7) == 0) { if (default_count > 0) { sprintf(base_name, "DEFAULT%d", default_count); } else { strcpy(base_name, "DEFAULT"); } default_count++; } ptr++; while(*ptr == ' ' || *ptr == '\t') { ptr++; } strcpy(content, ptr); content += strlen(content); mode = FIND_MODE_REPLY; lineuser = linenum; } *buffer = '\0'; } else { if(*buffer == ' ' || *buffer == '\t') { ptr = buffer; while(*ptr == ' ' || *ptr == '\t') { ptr++; } strcpy(content, ptr); content += strlen(content) - 1; /* strip trailing white space and comma */ while(*content == ' ' || *content == '\t' || *content == '\n' || *content == ',' ) { content--; } content++; *content = ','; content++; *content = '\0'; *buffer = '\0'; } else { /* We are done, leave buffer for next call */ if (*buffer == '\n') { *buffer = '\0'; } else { linenum--; } if(*(content - 1) == ',') { *(content-1) = '\0'; } return(0); } } } if (mode == FIND_MODE_REPLY) { /* return last entry */ *buffer = '\0'; if(*(content - 1) == ',') { *(content-1) = '\0'; } return (0); } fclose(userfd); return(-1); } /************************************************************************* * * Function: usage * * Purpose: Display the syntax for starting this program. * *************************************************************************/ void usage() { fprintf(stderr, "Usage: %s", progname); fprintf(stderr, " [-d ]"); fprintf(stderr, " [-h]"); fprintf(stderr, " [-v]"); fprintf(stderr, " [-x]\n"); exit(-1); } radiusd-livingston-2.1/src/conf/0042755000175000017500000000000006734250236014544 5ustar pmpmradiusd-livingston-2.1/src/conf/BSDOS_2.00100644000175000017500000000027006534526660015717 0ustar pmpm# System: BSDOS_2.0 - BSDI BSD/OS 2.0.1 i386 # # uncomment rsaref if you're building a USA Domestic binary # SSL_LIBS = -lssl -lcrypto #-lrsaref ILIBS = -lip $(SSL_LIBS) radiusd-livingston-2.1/src/conf/BSDOS_3.00100644000175000017500000000026606534526665015732 0ustar pmpm# System: BSDOS_3.0 - BSDI BSD/OS 3.0 i386 # # uncomment rsaref if you're building a USA Domestic binary # SSL_LIBS = -lssl -lcrypto #-lrsaref ILIBS = -lip $(SSL_LIBS) radiusd-livingston-2.1/src/conf/RS6000_4.20100644000175000017500000000021306552640522015672 0ustar pmpm# # RS6000_4.2 - IBM RS6000 AIX 4.2 # # Delete -DNOSHADOW if you are using shadow passwords # CPPFLAGS = -DSYS5 -Daix -DVSYSLOG -DNOSHADOW radiusd-livingston-2.1/src/conf/IRIX_6.30100644000175000017500000000005106351246605015617 0ustar pmpm# System: IRIX_6.3 - IP32 6.3 12161207 # radiusd-livingston-2.1/src/conf/Linux_1.20100644000175000017500000000011006351246605016131 0ustar pmpm# System: Linux 1.2.13 #4 Fri Nov 8 06:14:09 PST 1996 i586 # LIBS= -ldb radiusd-livingston-2.1/src/conf/Linux_2.00100644000175000017500000000017206573153243016141 0ustar pmpm# System: Linux 2.0.30 #6 Wed May 21 15:59:30 PDT 1997 i586 # Slackware 2.0 Linux # RADLIBS = $(OBJDIR)/libgdbm.a radiusd-livingston-2.1/src/conf/unixware0100644000175000017500000000066406535170214016326 0ustar pmpm# Contributed by a customer to compile on Unixware # Use BSD compatible compiler CC = /usr/ucb/cc COPT = -O # use -lgen library for vsyslog, crypt, getspnam, openlog, closelog LIBS = $(RADLIBS) -lgen # for some reason the unixware compiler won't write a.out to the right # place, instead it ignores the -o and write's to the current # directory... then the compile fails because the relevant object file # can't be found. OBJDIR = . radiusd-livingston-2.1/src/conf/hp9000_10.010100644000175000017500000000031706552643214016122 0ustar pmpm# System: HP-UX B.10.01 A 9000/712 # # delete the -DNOSHADOW if you are using shadow passwords # COPT = -O CPPFLAGS = -DNOSHADOW -DVSYSLOG LIBS = -lndbm -lsec ILIBS = -lip -lssl -lcrypto -lndbm -lsec -lM radiusd-livingston-2.1/src/conf/sun4_4.10100644000175000017500000000032406552630252015732 0ustar pmpm# System: sun4_4.1 - SunOS 4.1.4 2 sun4m # SSL_LIBS = -lssl -lcrypto #-lrsaref ILIBS = -lip $(SSL_LIBS) ICFLAGS= $(COPT) $(CPPFLAGS) $(SSL_CFLAGS) -I$(IPINCDIR) $(IPASS_CFLAGS) -DNO_STRERROR radiusd-livingston-2.1/src/conf/sun4_5.50100644000175000017500000000047106552572102015741 0ustar pmpm# System: sun4_5.5 - SunOS 5.5.1 Generic sun4m sparc # # Solaris uses shadow passwords, so do not use -DNOSHADOW # CPPFLAGS = -Dsys5 LIBS = -lsocket -lnsl # uncomment rsaref if you're building a USA Domestic binary of iradiusd # SSL_LIBS = -lssl -lcrypto #-lrsaref ILIBS = -lip $(SSL_LIBS) -lnsl -lsocket radiusd-livingston-2.1/src/conf/sun86_5.50100644000175000017500000000044706552644762016052 0ustar pmpm# System: sun86_5.5 - SunOS 5.5.1 generic i86pc i386 # # Solaris uses shadow passwords, so do not use -DNOSHADOW # CPPFLAGS = -Dsys5 LIBS = -lsocket -lnsl $(OBJDIR)/libgdbm.a # Add -lrsaref if you're building a USA Domestic binary of iradiusd # ILIBS = -lip -lssl -lcrypto $(LIBS) radiusd-livingston-2.1/src/conf/FreeBSD_2.20100644000175000017500000000017706533513470016261 0ustar pmpm# System: FREEBSD-2.2 - FreeBSD 2.2 # # This file should also work for NetBSD 1.2 and OpenBSD and FreeBSD 2.2 # LIBS = -lcrypt radiusd-livingston-2.1/src/conf/FreeBSD_2.10100644000175000017500000000010506430501154016237 0ustar pmpm# System: FREEBSD-2.1 - FreeBSD 2.1.7.1-RELEASE # LIBS = -ldescrypt radiusd-livingston-2.1/src/conf/alpha_4.00100644000175000017500000000103606552645144016134 0ustar pmpm# System: alpha_4.0 - OSF1 V4.0 564 alpha # # OSF/1 NDBM may have problems with large users files, we use GDBM instead. # # If you wish to use the OSF/1 system NDBM library instead of GDBM, # uncomment the first RADLIBS line and comment out the second RADLIBS line. # # GDBM source is available at no charge from the Free Software Foundation # at ftp://prep.ai.mit.edu/pub/gnu/ and is covered by the GNU Public License, # available at the same site. # CC=cc COPT = -g CPPFLAGS = -DNOSHADOW -DVSYSLOG RADLIBS = $(OBJDIR)/libgdbm.a radiusd-livingston-2.1/src/conf/alpha_2.00100644000175000017500000000024506552645124016131 0ustar pmpm# Linux 2.0.30 #3 Sat Mar 7 05:07:13 CST 1998 alpha # Redhat Linux 5.0 on Alpha # CC=cc COPT = -g CPPFLAGS = -DNOSHADOW -DVSYSLOG RADLIBS = -ldb -lcrypt radiusd-livingston-2.1/src/conf/hpux_10.200100644000175000017500000000033106567227751016175 0ustar pmpm# System: HP-UX B.10.20 A 9000/712 # # delete the -DNOSHADOW if you are using shadow passwords # CC = gcc COPT = -g CPPFLAGS = -DNOSHADOW -DVSYSLOG LIBS = -lndbm -lsec ILIBS = -lip -lssl -lcrypto -lndbm -lsec -lM radiusd-livingston-2.1/src/conf/Linux_5.20100644000175000017500000000014006734250551016140 0ustar pmpm# System: Linux 2.2.6 #20 Tue Apr 27 15:23:25 CDT 1999 i586 # Redhat Linux 5.2 # RADLIBS = -ldb radiusd-livingston-2.1/src/conf.h0100644000175000017500000000572706734270166014727 0ustar pmpm/* RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /* * $Id: conf.h,v 1.9 1999/06/23 23:40:38 cdr Exp $ */ #if !defined(NDBM) #define NDBM /* all supported platforms use NDBM now */ #endif #if defined(__alpha) typedef unsigned int UINT4; #else typedef unsigned long UINT4; #endif #if defined(unixware) || defined(sys5) || defined(M_UNIX) #include #else /* unixware */ #include #endif /* unixware */ #if defined(bsdi) #include #endif /* bsdi */ #if defined(bsdi) || defined(__FreeBSD__) #include #else /* bsdi */ #include #ifndef __USE_BSD extern char *sys_errlist[]; #endif /* _USE_BSD */ #endif /* bsdi */ #include #include #if defined(aix) #include #endif /* aix */ #if !defined(NDBM) #define dbm_fetch(db,x) fetch(x) #define dbm_close(db) dbm_close() #endif #if defined(SECURID) || defined(ACTIVCARD) #define SMARTCARD #endif #define VPORTS /* Enable virtual port feature */ /* #define PASSCHANGE *//* uncomment this to enable radpass -- not recommended */ radiusd-livingston-2.1/src/config.aeg0100644000175000017500000001066106446141463015542 0ustar pmpm# Rename this file to config.aeg after installing new ActivCard server # # ----------------------------------------------------------------- # This file contains the configuration information necessary for the # RADIUS server to connect to the ActivEngine, which is the # ActivCard Authentication Server. # ----------------------------------------------------------------- # ----------------------------------------------------------------- # ACTIVCARD_APPLICATION: APPLICATION_ID # # ActivCards contain up to four slots. Each slot contains a set # of independent DES keys and parameters, so that in practice an # ActivCard is equivalent to four «Tokens». Each of those «Tokens» # is called a slot and can be used to authenticate through an application # to a distinct ActivEngine. The concept that the ActivEngine uses to # decide which slot is to be used to verify a dynamic password (ultimately # which key among the set of keys stored for this token) is # the «Application» : Application (Server) -> Slot (Token) # # The following specifies the application to be used to determine the # token slot associated with RADIUS authentication requests from # the RADIUS server. # ----------------------------------------------------------------- ACTIVCARD_APPLICATION: RADIUS # ----------------------------------------------------------------- # ACTIVCARD_CHALLENGE: challenge_request_keyword # The ActivCards support simultaneously two authentication codes # for each given slot. One is a patented time/event synchronous mode # in which the user just types the one-time password displayed by his token # instead of the static vulnerable password he was used to. The other is # the standard X9.9, challenge/response mode. # ActivCard’s users can choose which mode they want to use by # typing a keyword at the RADIUS password prompt: # login: sam # password: challenge_request_keyword # Upon reception of this keyword the ActivCard component embedded in the # RADIUS server will switch to challenge/response mode and issue a # challenge (a very good quality random number), and the user will be prompted # for a dynamic password: # login: sam # password: challenge_request_keyword # # Challenge/Response Authentication requested... # Challenge: 12345678 # Response: # The user has to type the challenge into his token and type at the prompt the # dynamic password produced by the token for that challenge. # ----------------------------------------------------------------- ACTIVCARD_CHALLENGE: challenge # ----------------------------------------------------------------- # ACTIVCARD_HOST: 192.168.15.60 # The following parameter indicates the ip address of the machine where the # ActivEngine is located. # ----------------------------------------------------------------- ACTIVCARD_HOST: 192.168.15.60 # ----------------------------------------------------------------- # ACTIVCARD_AUTHPORT: 8866 # The following parameter specifies the port to which the ActivEngine # will be listening for authentication requests. # ----------------------------------------------------------------- ACTIVCARD_AUTHPORT: 8866 # ----------------------------------------------------------------- # ACTIVCARD_SESSTIMEOUT: 25 # This parameter specifies the timeout value to use when the RADIUS # server connects to the ActivEngine. # ----------------------------------------------------------------- ACTIVCARD_SESSTIMEOUT: 25 # ----------------------------------------------------------------- # ACTIVCARD_SECPOLICY: 0 # This parameter specifies which type of connection will be established # with the ActivEngine: 0(NEGOTIATE), 1(ENCRYPTED), 2(NON-ENCRYPTED). # The ActivEngine client component and its server counterpart can establish # a secure channel based on a Diffie-Hellman key exchange. # ----------------------------------------------------------------- ACTIVCARD_SECPOLICY: 0 # ----------------------------------------------------------------- # ACTIVCARD_PUBKEY: # The ActivEngine Diffie-Hellman public key used to establish a secure channel # between the RADIUS server and the ActivEngine. # # At the time of installation of the ActivEngine, a distribution file called # «aeg.dis» is generated. It contains the information necessary to # establish the connection to the ActivEngine as well as the value of the # public key of the ActivEngine # ----------------------------------------------------------------- ACTIVCARD_PUBKEY: 4807E...get this from the ActivEngine distribution file. radiusd-livingston-2.1/src/dbmkeys.c0100644000175000017500000000614506734270166015426 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: dbmkeys.c,v 1.8 1999/06/23 23:40:38 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include "radius.h" #ifdef NDBM # include #else /* not NDBM */ # include #endif /* not NDBM */ extern int errno; extern char *sys_errlist[]; main(argc, argv) int argc; char * argv[]; { datum key; #ifdef NDBM DBM *db; #endif /* NDBM */ int i; #ifdef NDBM if ((db = dbm_open("raddb/users", O_RDONLY, 0)) == (DBM *)NULL) #else /* not NDBM */ if(dbminit("raddb/users") != 0) #endif /* not NDBM */ { printf("Couldn't open DBM file error<%s>\n", sys_errlist[errno]); exit(errno); } for (i=1; ; i++) { if (i == 1) { #ifdef NDBM key = dbm_firstkey(db); #else /* not NDBM */ key = firstkey(db); #endif /* not NDBM */ } else { #ifdef NDBM key = dbm_nextkey(db); #else /* not NDBM */ key = nextkey(key); #endif /* not NDBM */ } if(key.dsize == 0) { break; } key.dptr[key.dsize] = 0; printf(" %4d key <%s>\n", i, key.dptr); } #ifdef NDBM dbm_close(db); #else /* not NDBM */ dbmclose(); #endif /* not NDBM */ exit(0); } radiusd-livingston-2.1/src/dbmrec.c0100644000175000017500000001141606734270167015222 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: dbmrec.c,v 1.10 1999/06/23 23:40:39 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include "radius.h" #ifdef NDBM # include #else /* not NDBM */ # include #endif /* NDBM */ int radius_dbm; char *radius_dir; char *radius_log; char *progname; int accept_zero = 0; int debug_flag = 0; int debug_mem = 0; extern int errno; extern char * sys_errlist[]; int main(argc, argv) int argc; char * argv[]; { VALUE_PAIR *values; char *ptr; datum key; datum rec; int dict_init(); int userparse(); void pairfree(); void show_val(); void usage(); void log_version(); #ifdef NDBM DBM *db; #endif /* NDBM */ progname = argv[0]; if (argc != 2) { usage(); } radius_dbm = 1; radius_dir = "raddb"; radius_log = "/dev/tty"; log_version(); if(dict_init() != 0) { printf("dict_init FAILED\n"); exit(1); } #ifdef NDBM if ((db = dbm_open("raddb/users", O_RDONLY, 0)) == (DBM *)NULL) #else /* not NDBM */ if(dbminit("raddb/users") != 0) #endif /* NDBM */ { printf("Couldn't open DBM file error<%s>\n", sys_errlist[errno]); exit(errno); } key.dptr = argv[1]; key.dsize = strlen(key.dptr); #ifdef NDBM rec = dbm_fetch(db, key); #else /* not NDBM */ rec = fetch(key); #endif /* NDBM */ if (rec.dsize == 0) { printf("Record <%s> not found!\n", key.dptr); } else { printf("Recode <%s> len %d\n", key.dptr, rec.dsize); ptr = rec.dptr; rec.dptr[rec.dsize] = '\0'; values = (VALUE_PAIR *)NULL; /* * Parse check values */ if(userparse(ptr, &values) != 0) { log_err("userparse ERROR\n"); } show_val("Check", values); pairfree(values,"main"); values = (VALUE_PAIR *)NULL; while(*ptr != '\n' && *ptr != '\0') { ptr++; } if(*ptr == '\n') { ptr++; /* * Parse reply values */ if(userparse(ptr, &values) != 0) { log_err("userparse ERROR\n"); } show_val("Reply", values); pairfree(values,"main"); } } #ifdef NDBM dbm_close(db); #else /* not NDBM */ dbmclose(); #endif /* NDBM */ exit(0); } void show_val(str, vp) char *str; VALUE_PAIR *vp; { printf("%s values:\n", str); while (vp) { printf(" <%s> = ", vp->name); switch(vp->type) { case PW_TYPE_STRING: printf("<%s>\n", vp->strvalue); break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: printf("<%x>\n",(unsigned int)vp->lvalue); break; } vp = vp->next; } } VALUE_PAIR * get_attribute(value_list, attribute) VALUE_PAIR *value_list; int attribute; { while(value_list != (VALUE_PAIR *)NULL) { if(value_list->attribute == attribute) { return(value_list); } value_list = value_list->next; } return((VALUE_PAIR *)NULL); } void usage() { printf("usage: %s \n", progname); exit(1); } void rad_exit(rc) int rc; { exit(rc); } radiusd-livingston-2.1/src/dict.c0100644000175000017500000002507406734270167014716 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: dict.c,v 1.13 1999/06/23 23:40:39 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include "radius.h" extern char *progname; extern int debug_flag; extern char *radius_dir; static DICT_ATTR *dictionary_vendors; static DICT_ATTR *dictionary_attributes; static DICT_VALUE *dictionary_values; /************************************************************************* * * Function: dict_init * * Purpose: Initialize the dictionary. Read all ATTRIBUTES into * the dictionary_attributes list. Read all VALUES into * the dictionary_values list. * *************************************************************************/ int dict_init() { FILE *dictfd; char dummystr[64]; char namestr[64]; char valstr[64]; char attrstr[64]; char typestr[64]; char vendorstr[64]; int line_no; DICT_ATTR *attr; DICT_VALUE *dval; char buffer[256]; char dictfile[256]; int value; int type; int atoi(); int dict_vendor(); int fclose(); sprintf(dictfile, "%s/%s", radius_dir, RADIUS_DICTIONARY); if((dictfd = fopen(dictfile, "r")) == (FILE *)NULL) { log_err("could not read dictionary file %s\n",dictfile); return(-1); } line_no = 0; while(fgets(buffer, sizeof(buffer), dictfd) != (char *)NULL) { line_no++; /* Skip empty space */ if(*buffer == '#' || *buffer == '\0' || *buffer == '\n') { continue; } if(strncmp(buffer, "ATTRIBUTE", 9) == 0) { vendorstr[0] = '\0'; /* Read the ATTRIBUTE line */ if(sscanf(buffer, "%s%s%s%s%s", dummystr, namestr, valstr, typestr,vendorstr) < 4) { log_err("invalid attribute on line %d of dictionary file %s\n", line_no,dictfile); return(-1); } /* * Validate all entries */ if((int)strlen(namestr) > 31) { log_err("attribute name too long on line %d of dictionary %s\n", line_no, dictfile); return(-1); } if(!isdigit(*valstr)) { log_err("attribute has non-numeric value on line %d of dictionary %s\n", line_no, dictfile); return(-1); } value = atoi(valstr); if(strcmp(typestr, "string") == 0) { type = PW_TYPE_STRING; } else if(strcmp(typestr, "integer") == 0) { type = PW_TYPE_INTEGER; } else if(strcmp(typestr, "ipaddr") == 0) { type = PW_TYPE_IPADDR; } else if(strcmp(typestr, "date") == 0) { type = PW_TYPE_DATE; } else { log_err("attribute has unknown type on line %d of dictionary %s\n", line_no, dictfile); return(-1); } /* Create a new attribute for the list */ if((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) == (DICT_ATTR *)NULL) { log_err("ran out of memory after reading line %d of dictionary %s\n",line_no,dictfile); return(-1); } strcpy(attr->name, namestr); attr->type = type; if (*vendorstr) { /* Vendor-Specific */ attr->value = PW_VENDOR; attr->vsvalue = value; attr->vendor = dict_vendor(vendorstr); } else { attr->value = value; attr->vsvalue = 0; attr->vendor = 0; } /* Insert it into the list */ attr->next = dictionary_attributes; dictionary_attributes = attr; } else if(strncmp(buffer, "VALUE", 5) == 0) { /* Read the VALUE line */ if(sscanf(buffer, "%s%s%s%s", dummystr, attrstr, namestr, valstr) != 4) { log_err("Invalid value entry on line %d of dictionary %s\n", line_no, dictfile); return(-1); } /* * Validate all entries */ if((int)strlen(attrstr) > 31) { log_err("attribute name too long on line %d of dictionary %s\n", line_no, dictfile); return(-1); } if((int)strlen(namestr) > 31) { log_err("value name too long on line %d of dictionary %s\n", line_no, dictfile); return(-1); } if(!isdigit(*valstr)) { log_err("value has non-numeric value on line %d of dictionary %s\n", line_no, dictfile); return(-1); } value = atoi(valstr); /* Create a new VALUE entry for the list */ if((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) == (DICT_VALUE *)NULL) { log_err("ran out of memory after reading line %d of dictionary %s\n",line_no,dictfile); return(-1); } strcpy(dval->attrname, attrstr); strcpy(dval->name, namestr); dval->value = value; /* Insert it into the list */ dval->next = dictionary_values; dictionary_values = dval; } else if(strncmp(buffer, "VENDOR", 6) == 0) { /* Read the VENDOR line */ if(sscanf(buffer, "%s%s%s", dummystr, namestr, valstr) < 3) { log_err("invalid vendor on line %d of dictionary file %s\n", line_no, dictfile); return(-1); } /* * Validate all entries */ if((int)strlen(namestr) > 31) { log_err("vendor name too long on line %d of dictionary %s\n", line_no, dictfile); return(-1); } if(!isdigit(*valstr)) { log_err("vendor \"%s\" has non-numeric value \"%s\" on line %d of dictionary %s\n", namestr, valstr, line_no, dictfile); return(-1); } value = atoi(valstr); /* Create a new vendor for the list */ if((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) == (DICT_ATTR *)NULL) { log_err("ran out of memory after reading line %d of dictionary %s\n",line_no,dictfile); return(-1); } strcpy(attr->name, namestr); attr->vendor = value; attr->type = 0; attr->value = 0; attr->vsvalue = 0; /* Insert it into the list */ attr->next = dictionary_vendors; dictionary_vendors = attr; } } fclose(dictfd); return(0); } /************************************************************************* * * Function: dict_attrget * * Purpose: Return the full attribute structure based on the * attribute id number * *************************************************************************/ DICT_ATTR * dict_attrget(attribute) int attribute; { DICT_ATTR *attr; attr = dictionary_attributes; while(attr != (DICT_ATTR *)NULL) { if(attr->value == attribute) { return(attr); } attr = attr->next; } return((DICT_ATTR *)NULL); } /************************************************************************* * * Function: dict_vsattrget * * Purpose: Return the full attribute structure based on the * vendor code and vendor subattribute * *************************************************************************/ DICT_ATTR * dict_vsattrget(vendor,vsa) int vendor; int vsa; { DICT_ATTR *attr; attr = dictionary_attributes; while(attr != (DICT_ATTR *)NULL) { if(attr->value == PW_VENDOR && attr->vendor == vendor && attr->vsvalue == vsa) { return(attr); } attr = attr->next; } return((DICT_ATTR *)NULL); } /************************************************************************* * * Function: dict_attrfind * * Purpose: Return the full attribute structure based on the * attribute name. * *************************************************************************/ DICT_ATTR * dict_attrfind(attrname) char *attrname; { DICT_ATTR *attr; attr = dictionary_attributes; while(attr != (DICT_ATTR *)NULL) { if(strcmp(attr->name, attrname) == 0) { return(attr); } attr = attr->next; } return((DICT_ATTR *)NULL); } /************************************************************************* * * Function: dict_valfind * * Purpose: Return the full value structure based on the * value name. * *************************************************************************/ DICT_VALUE * dict_valfind(valname) char *valname; { DICT_VALUE *val; val = dictionary_values; while(val != (DICT_VALUE *)NULL) { if(strcmp(val->name, valname) == 0) { return(val); } val = val->next; } return((DICT_VALUE *)NULL); } /************************************************************************* * * Function: dict_valget * * Purpose: Return the full value structure based on the * actual value and the associated attribute name. * *************************************************************************/ DICT_VALUE * dict_valget(value, attrname) UINT4 value; char *attrname; { DICT_VALUE *val; val = dictionary_values; while(val != (DICT_VALUE *)NULL) { if(strcmp(val->attrname, attrname) == 0 && val->value == value) { return(val); } val = val->next; } return((DICT_VALUE *)NULL); } /************************************************************************* * * Function: dict_vendor * * Purpose: Return the vendor number based on the vendor name. * *************************************************************************/ int dict_vendor(vendname) char *vendname; { DICT_ATTR *vend; vend = dictionary_vendors; while (vend != (DICT_ATTR *)NULL) { if (strcmp(vend->name, vendname) == 0) { return(vend->vendor); } vend = vend->next; } return(atoi(vendname)); } radiusd-livingston-2.1/src/ipass.c0100644000175000017500000003105006734270167015101 0ustar pmpm/* * ipass.c - Ipass alliance routines * * These routines are called by the main program to talk to an Ipass server. * * The samples we have provided here may be used at a site running RADIUS */ /* * * Copyright 1996 iPass Alliance Inc. All rights reserved. * * Portions may be copyright by: * * Lucent Technologies Remote Access * 4464 Willow Road * Pleasanton, CA 94588 * * Copyright 1992-1999 Lucent Technologies, Inc. * */ #ifdef IPASS #ident "@(#)$Name: $:$Id: ipass.c,v 1.2 1999/06/23 23:40:39 cdr Exp $" #include #include #ifdef HAVE_SYS_CDEFS_H # include #endif #include #if HAVE_SYS_WAIT_H # include #endif #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif #include #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_MEMORY_H # include #endif #if STDC_HEADERS # include # include #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif # ifdef HAVE_STRINGS_H # include # endif /* XXX should really declare string functions here... */ # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy((s), (d), (n)) # define memmove(d, s, n) bcopy((s), (d), (n)) # endif #endif #include #include #include #include #include #include #include "radius.h" /* includes local md5.h */ #define IPASS_REMOTE_ID_CHAR '@' struct sockaddr_in rad_addr,cli_addr; extern int server_fd; extern int errno; /* forward declarations */ int ipassinit(); int decode_passwd (char *, UINT4, char *, char *); void handle_response (int, AUTH_REQ *, ipinfo_t *, ipauth_t *, int, int); void dump_to_disk (char *, int, char *); int raddebug = 0; int ipassinit() { /* init iPass library */ return ipass_init(0, (char **) NULL, IPASS_PROGNM_AUTHD); } int rad_forw_ipass(authreq, radius_fd, buff) AUTH_REQ *authreq; int radius_fd; char *buff; { AUTH_HDR *auth; ipinfo_t ipinfo; ipauth_t ipauth; ipacct_t ipacct; char *ptr,*sptr, *p; char ibuff[BUFSIZ]; char vector[16]; char passwd[128]; char user_name[IPASS_MAXNAMLEN+IPASS_MAXDOMLEN+1+1]; char nas_ip[(4*3)+3+1]; int attrvalue, i,j; u_short length, attribute, attrlen; int ret_code = 0; time_t ttime; auth = (AUTH_HDR*)buff; ipinfo.service = IPASS_SERV_UNKNOWN; ipinfo.direction = IPASS_DIR_UNKNOWN; ipinfo.nas_ses_id[0] = '\0'; ipauth.host_ip.s_addr = INADDR_ANY; ipacct.user_ip.s_addr = INADDR_ANY; ipacct.user_mask.s_addr = INADDR_ANY; passwd[0] = '\0'; ipauth.passwd[0] = '\0'; switch(auth->code){ case PW_AUTHENTICATION_REQUEST: trace("received authentication request, id: %d", auth->id); break; case PW_ACCOUNTING_REQUEST: trace("received accounting request, id: %d", auth->id); break; default: trace("received unknown request: %d", auth->code); return; } ptr=&buff[4]; for (i=0;ilength); ptr=&buff[0]; ptr+=AUTH_HDR_LEN; length-=AUTH_HDR_LEN; /* now pointing at code of first data field */ if (raddebug){ dump_to_disk((char *)buff,(int)auth->length,"Request"); } while (length > 2) { attribute = *ptr++; attrlen = *ptr++; sptr=ptr; if (attrlen < 2) { /* malformed packet, can't do anything but quit */ length = 0; continue; } if (attrlen == 2){ /* this is illegal, but one site who shall remain nameless sends these packets all the time */ length -= 2; continue; } attrlen -= 2; ptr+=attrlen-1; attrvalue=*ptr++; switch (attribute){ case PW_CLIENT_ID: memcpy(&ipinfo.nas_ip, sptr, sizeof(UINT4)); sptr += 4; break; case PW_LOGIN_HOST: memcpy(&ipauth.host_ip, sptr, sizeof(UINT4)); sptr += 4; break; case PW_PASSWORD: for(i=0;icode == PW_AUTHENTICATION_REQUEST){ if (passwd[0]) { if (!decode_passwd(passwd, authreq->ipaddr, auth->vector, authreq->secret)) return -1; strncpy(ipauth.passwd, passwd, sizeof(ipauth.passwd) - 1); ipauth.passwd[sizeof(ipauth.passwd) - 1] = '\0'; } ipass_remote_auth(&ipinfo, &ipauth); if (ipauth.errcode != IPASS_STATUS_OK) { trace("ipass_remote_auth: failed %d: %s", ipauth.errcode, ipauth.status ? ipauth.status : ""); return -1; } ret_code = ipauth.auth_reply == IPASS_AUTH_OK ? 1 : 0; } else{ ipacct.ip = 0; ipacct.op = 0; ipacct.ic = 0; ipacct.oc = 0; ipass_remote_acct(&ipinfo, &ipacct); if (ipacct.errcode != IPASS_STATUS_OK) { trace("ipass_remote_acct: failed %d: %s", ipacct.errcode, ipacct.status ? ipacct.status : ""); return -1; } ret_code = 1; } handle_response(radius_fd,authreq, &ipinfo,&ipauth,auth->code,ret_code); return 1; } /* handle_response - decode reply from ipass and send the return packet back to NAS */ void handle_response (radius_fd,authreq,ipinfop,ipauthp, auth_code,ret_code) int radius_fd; AUTH_REQ *authreq; ipinfo_t *ipinfop; ipauth_t *ipauthp; int auth_code; int ret_code; { AUTH_HDR *authreply; int i; char *ptr; UINT4 lvalue; u_short length; unsigned char replybuff[4096]; unsigned char vector[AUTH_VECTOR_LEN]; struct sockaddr_in nas_addr; authreply = (AUTH_HDR *)replybuff; memset(replybuff,0,sizeof(replybuff)); /* start building reply packet */ authreply->id = authreq->id; memcpy(authreply->vector,authreq->vector,AUTH_VECTOR_LEN); length=AUTH_HDR_LEN; authreply->code = PW_AUTHENTICATION_REJECT; if (ret_code) { ptr = (char *) authreply->data; if (auth_code == PW_AUTHENTICATION_REQUEST) { authreply->code = PW_AUTHENTICATION_ACK; if ((ipauthp->serv_req == IPASS_SERV_RLOGIN)|| (ipauthp->serv_req == IPASS_SERV_TELNET)|| (ipauthp->serv_req == IPASS_SERV_PPP)|| (ipauthp->serv_req == IPASS_SERV_SLIP)){ *ptr++ = PW_USER_SERVICE_TYPE; *ptr = 6; length += *ptr; ptr += 4; switch (ipauthp->serv_req) { case IPASS_SERV_RLOGIN: case IPASS_SERV_TELNET: *ptr++ = PW_LOGIN_USER; *ptr++ = PW_LOGIN_SERVICE; *ptr = 6; length += *ptr; ptr += 4; if (ipauthp->serv_req == IPASS_SERV_TELNET) *ptr++ = PW_TELNET; else *ptr++ = PW_RLOGIN; break; case IPASS_SERV_PPP: case IPASS_SERV_SLIP: *ptr++ = PW_FRAMED_USER; *ptr++ = PW_FRAMED_PROTOCOL; *ptr = 6; length += *ptr; ptr += 4; if (ipauthp->serv_req == IPASS_SERV_PPP) *ptr++ = PW_PPP; else *ptr++ = PW_SLIP; break; } if (ipauthp->host_ip.s_addr != INADDR_ANY) { *ptr++ = PW_LOGIN_HOST; *ptr++ = sizeof(UINT4) + 2; memcpy(ptr, &ipauthp->host_ip.s_addr, sizeof(UINT4)); ptr += sizeof(UINT4); length += sizeof(UINT4) + 2; } if (ipauthp->host_port) { *ptr++ = PW_LOGIN_TCP_PORT; *ptr++ = sizeof(UINT4) + 2; lvalue = htons(ipauthp->host_port); memcpy(ptr, &lvalue, sizeof(UINT4)); ptr += sizeof(UINT4); length += sizeof(UINT4) + 2; } } else{ trace("unsupported iPass service request %d, ignored.", ipauthp->serv_req); } } else authreply->code = PW_ACCOUNTING_RESPONSE; } authreply->length = htons(length); memcpy(replybuff+length,authreq->secret,strlen(authreq->secret)); md5_calc(vector,replybuff,length+strlen(authreq->secret)); memcpy(authreply->vector,vector,AUTH_VECTOR_LEN); /* don't need secret anymore, trash it from reply packet */ memset(replybuff+length,0,strlen(authreq->secret)); memset((char*) &nas_addr,0, sizeof(nas_addr)); nas_addr.sin_family = AF_INET; nas_addr.sin_addr.s_addr = htonl(authreq->ipaddr); nas_addr.sin_port = htons(authreq->udp_port); if (sendto(radius_fd,(char*)replybuff,length,0, (struct sockaddr*)&nas_addr,sizeof(nas_addr)) == -1) { trace("remote sendto NAS %s failed, error %d", ipaddr2strp(ntohl(nas_addr.sin_addr.s_addr)), errno); } else { trace("remote sendto NAS %s okay", ipaddr2strp(ntohl(nas_addr.sin_addr.s_addr))); } if (raddebug) { dump_to_disk((char *)replybuff,(int)length,"Reply"); } return; } int decode_passwd (passwd,ipaddr,vector,shared_secret) char *passwd; UINT4 ipaddr; char *vector; char *shared_secret; { unsigned char md5obuf[256]; unsigned char md5ibuf[256]; int i,j; for (i=0;i 0) { fprintf(fp,"%3x ",j); j+=16; for (i=0; i<16; i++,bp++,count--) { if (count > 0) { fprintf(fp,"%s ",X2(*bp)); ASC[i] = '.'; if (*bp >= ' ' && *bp <= '~') ASC[i] = *bp; } else { fprintf(fp," "); ASC[i] = ' '; } if (i == 7) fprintf(fp," "); } ASC[16] = 0; fprintf(fp," *%s*\n",ASC); } /**/ fclose(fp); /**/ } char *X2 (val) register int val; { static char buff[3]; register int x; x = (val>>4) & 0xf; if (x >= 10) x += 'A' - 10; else x+= '0'; buff[0] = (char) x; x = val & 0xf; if (x >= 10) x += 'A' - 10; else x+= '0'; buff[1] = (char) x; buff[2] = 0; return(buff); } #ifdef NO_STRERROR /* * system has no strerror in standard libraries, so define our own */ char * strerror(err) int err; { extern int sys_nerr; static char *unknown = "unknown errno"; if (err < sys_nerr) { return sys_errlist[err]; } return unknown; } #endif /* NO_STRERROR */ #else /* IPASS */ #include #include "radius.h" /* XXX includes local md5.h */ /* dummy entry points */ int ipassinit() { return 0; } int rad_forw_ipass(authreq, activefd, buffer) AUTH_REQ *authreq; int activefd; char *buffer; { extern char *progname; char *req2strp(); log_err("%s: no ipass support, %s cannot be forwarded\n", progname, req2strp(authreq)); return 0; } #endif /* IPASS */ radiusd-livingston-2.1/src/log.c0100644000175000017500000001012506734270167014543 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: log.c,v 1.10 1999/06/23 23:40:39 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include extern char *radius_log; extern char *progname; void log_msg(); /************************************************************************* * * Function: log_err * * Purpose: Log the error message * *************************************************************************/ void log_err(char * fmt, ...) { va_list args; va_start(args, fmt); log_msg(LOG_ERR, fmt, args); va_end(args); } /************************************************************************* * * Function: log_debug * * Purpose: Log the debug message * *************************************************************************/ void log_debug(char * fmt, ...) { va_list args; va_start(args, fmt); log_msg(LOG_DEBUG, fmt, args); va_end(args); } /************************************************************************* * * Function: log_msg * * Purpose: Log the priority message * *************************************************************************/ void log_msg(priority, fmt, args) int priority; char *fmt; va_list args; { FILE *msgfd; int vfprintf(); pid_t getpid(); time_t time(); time_t timeval; void closelog(); int fclose(); int fflush(); #ifdef VSYSLOG char buffer[1024]; int vsprintf(); #else void vsyslog(); #endif /* VSYSLOG */ if (radius_log) { /* * use users option logfile [-l ] */ if((msgfd = fopen(radius_log, "a")) == (FILE *)NULL) { fprintf(stderr, "%s: could not open %s for logging\n", progname, radius_log); return; } timeval = time(0); fprintf(msgfd, "%-24.24s: [%d] ", ctime(&timeval),(int)getpid()); vfprintf(msgfd, fmt, args); fflush(msgfd); fclose(msgfd); } else { /* * use syslog */ openlog("radius", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH); #ifdef VSYSLOG vsprintf(buffer, fmt, args); syslog(priority, buffer); #else /* not VSYSLOG */ vsyslog(priority, fmt, args); #endif /* not VSYSLOG */ closelog(); } return; } radiusd-livingston-2.1/src/md5.c0100644000175000017500000002472706336531014014451 0ustar pmpm/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "md5.h" /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } void md5_calc(output, input, inlen) unsigned char *output; unsigned char *input; /* input block */ unsigned int inlen; /* length of input block */ { MD5_CTX context; MD5Init(&context); MD5Update(&context, input, inlen); MD5Final(output, &context); } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void MD5Update (context, input, inputLen) MD5_CTX *context; /* context */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) context->count[1]++; context->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ void MD5Final (digest, context) unsigned char digest[16]; /* message digest */ MD5_CTX *context; /* context */ { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen); /* Append length (before padding) */ MD5Update (context, bits, 8); /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset ((POINTER)context, 0, sizeof (*context)); } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform (state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ MD5_memset ((POINTER)x, 0, sizeof (x)); } /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode (output, input, len) unsigned char *output; UINT4 *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ static void Decode (output, input, len) UINT4 *output; unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD5_memcpy (output, input, len) POINTER output; POINTER input; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset (output, value, len) POINTER output; int value; unsigned int len; { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } radiusd-livingston-2.1/src/md5.h0100644000175000017500000000423006557257067014463 0ustar pmpm/* GLOBAL.H - RSAREF types and constants */ /* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ #if defined(__alpha) typedef unsigned int UINT4; #else typedef unsigned long int UINT4; #endif /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); radiusd-livingston-2.1/src/md5test.c0100644000175000017500000000601506734270170015344 0ustar pmpm/* * md5test - calculate md5 checksum for testing purposes */ /*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: md5test.c,v 1.2 1999/06/23 23:40:40 cdr Exp $ Copyright 1999 Lucent Technologies Inc"; /* Usage: md5test takes the shared secret as an argument, reads a hex dump on standard input, and outputs the length, shared secret, standard input, followed by the MD5 checksum of that input followed by the shared secret. This skeleton program is useful combined with radiusd -x -x to make sure that the right checksums are being calculated */ #include #include main(argc,argv) int argc; char **argv; { u_char buf[256],pw_digest[16]; int h; int i,n = 0,len; *argv++; while (scanf("%2x",&h) != EOF) { buf[n++] = h & 0xff; } printf("%d %s\n",n,*argv); len=strlen(*argv); memcpy(&buf[n],*argv,len); md5_calc(pw_digest, buf, n+len); for (i=0;i #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" extern char *radius_dir; extern char *radacct_dir; extern char *progname; void process_menu(authreq, activefd, pw_digest) AUTH_REQ *authreq; int activefd; char *pw_digest; { VALUE_PAIR *attr; VALUE_PAIR *term_attr; VALUE_PAIR *newattr; VALUE_PAIR *get_attribute(); VALUE_PAIR *menu_pairs(); VALUE_PAIR *pairalloc(); char menu_name[128]; char menu_input[32]; int i; char state_value[128]; void send_accept(); void send_reject(); void pairfree(); void reqfree(); if((attr = get_attribute(authreq->request, PW_STATE)) != (VALUE_PAIR *)NULL && strncmp(attr->strvalue, "MENU=", 5) == 0){ strcpy(menu_name, &attr->strvalue[5]); /* The menu input is in the Password Field */ attr = get_attribute(authreq->request, PW_PASSWORD); if(attr == (VALUE_PAIR *)NULL) { *menu_input = '\0'; } else { /* * Decrypt the password in the request. */ memcpy(menu_input, attr->strvalue, AUTH_PASS_LEN); for(i = 0;i < AUTH_PASS_LEN;i++) { menu_input[i] ^= pw_digest[i]; } menu_input[AUTH_PASS_LEN] = '\0'; } attr = menu_pairs(menu_name, menu_input); } /* handle termination menu */ if((term_attr = get_attribute(attr, PW_TERMINATION_MENU)) != (VALUE_PAIR *)NULL) { /* Change this to a menu state */ sprintf(state_value, "MENU=%s", term_attr->strvalue); term_attr->attribute = PW_STATE; strcpy(term_attr->strvalue, state_value); strcpy(term_attr->name, "Challenge-State"); /* Insert RADIUS termination option */ /* Set termination values */ newattr = pairalloc("process_menu"); newattr->attribute = PW_TERMINATION; newattr->type = PW_TYPE_INTEGER; newattr->lvalue = PW_TERM_RADIUS_REQUEST; strcpy(newattr->name, "Termination-Action"); /* Insert it */ newattr->next = term_attr->next; term_attr->next = newattr; } if((term_attr = get_attribute(attr, PW_MENU)) != (VALUE_PAIR *)NULL && strcmp(term_attr->strvalue, "EXIT") == 0) { send_reject(authreq, (char *)"", activefd); pairfree(attr,"process_menu"); } else if(attr != (VALUE_PAIR *)NULL) { send_accept(authreq, attr, (char *)NULL, activefd); pairfree(attr,"process_menu"); } else { send_reject(authreq, (char *)NULL, activefd); } reqfree(authreq,"process_menu"); return; } char * get_menu(menu_name) char *menu_name; { FILE *fd; static char menu_buffer[4096]; int mode; char *ptr; int nread; int len; sprintf(menu_buffer, "%s/menus/%s", radius_dir, menu_name); if((fd = fopen(menu_buffer, "r")) == (FILE *)NULL) { return("\r\n*** User Menu is Not Available ***\r\n"); } mode = 0; nread = 0; ptr = menu_buffer; *ptr = '\0'; while(fgets(ptr, 4096 - nread, fd) != NULL && nread < 4096) { if(mode == 0) { if(strncmp(ptr, "menu", 4) == 0) { mode = 1; } } else { if(strncmp(ptr, "end\n", 4) == 0) { if(ptr > menu_buffer) { *(ptr - 2) = '\0'; } else { *ptr = '\0'; } return(menu_buffer); } len = strlen(ptr); ptr += len - 1; *ptr++ = '\r'; *ptr++ = '\n'; nread += len + 1; } } *ptr = '\0'; return(menu_buffer); } VALUE_PAIR * menu_pairs(menu_name, menu_selection) char *menu_name; char *menu_selection; { FILE *fd; char buffer[4096]; char selection[32]; int mode; char *ptr; int nread; int userparse(); VALUE_PAIR *reply_first; void pairfree(); int fclose(); sprintf(buffer, "%s/menus/%s", radius_dir, menu_name); if((fd = fopen(buffer, "r")) == (FILE *)NULL) { return((VALUE_PAIR *)NULL); } /* Skip past the menu */ mode = 0; nread = 0; while(fgets(buffer, sizeof(buffer), fd) != NULL) { if(mode == 0) { if(strncmp(buffer, "menu", 4) == 0) { mode = 1; } } else { if(strncmp(buffer, "end\n", 4) == 0) { break; } } } /* handle default */ if(*menu_selection == '\0') { strcpy(selection, ""); } else { strcpy(selection, menu_selection); } reply_first = (VALUE_PAIR *)NULL; /* Look for a matching menu entry */ while(fgets(buffer, sizeof(buffer), fd) != NULL) { /* Terminate the buffer */ ptr = buffer; while(*ptr != '\n' && *ptr != '\0') { ptr++; } if(*ptr == '\n') { *ptr = '\0'; } if(strcmp(selection, buffer) == 0 || strcmp("DEFAULT", buffer) == 0) { /* We have a match */ while(fgets(buffer, sizeof(buffer), fd) != NULL) { if(*buffer == ' ' || *buffer == '\t') { /* * Parse the reply values */ if(userparse(buffer, &reply_first) != 0) { log_err("parse error for menu %s\n",menu_name); pairfree(reply_first,"menu_pairs"); fclose(fd); return((VALUE_PAIR *)NULL); } } else { /* We are done */ fclose(fd); return(reply_first); } } fclose(fd); return(reply_first); } } fclose(fd); return((VALUE_PAIR *)NULL); } radiusd-livingston-2.1/src/pass.c0100644000175000017500000001460106734270170014725 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: pass.c,v 1.2 1999/06/23 23:40:40 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include "radius.h" #include "users.h" #if !defined(NOSHADOW) #include #endif /* !NOSHADOW */ struct passwd pw; char pwbuf[MAX_LINE_SIZE]; extern int debug_flag; extern char *alt_passwd; /************************************************************************* * * Function: unix_pass * * Purpose: Check the users password against the standard UNIX * password table. * *************************************************************************/ int unix_pass(name, passwd, from) char *name; char *passwd; char *from; { struct passwd *pwd; struct passwd *getownpwnam(); struct passwd *getpwnam(); char *encpw; char *crypt(); char *encrypted_pass; #if !defined(NOSHADOW) #if defined(M_UNIX) struct passwd *spwd; #else struct spwd *spwd; #endif #endif /* !NOSHADOW */ /* Get encrypted password from alternate password file */ if (alt_passwd != (char *)NULL) { if((pwd = getownpwnam(name)) == NULL) { DEBUG("unix_pass: getownpwnam for \"%s\"%s failed\n", name, from); return(-1); } encrypted_pass = pwd->pw_passwd; } else { /* Get encrypted password from password file */ if((pwd = getpwnam(name)) == NULL) { DEBUG("unix_pass: getpwnam for \"%s\"%s failed\n", name, from); return(-1); } #if defined(BSD4_4) /* Return failed if Unix Account is expired (locked out) */ if (pwd->pw_expire && (pwd->pw_expire < time((time_t *)NULL))) { DEBUG("unix_pass: account for \"%s\"%s has expired\n", name, from); return(-1); } #endif encrypted_pass = pwd->pw_passwd; #if !defined(NOSHADOW) if(strcmp(pwd->pw_passwd, "x") == 0 || strcmp(pwd->pw_passwd, "*") == 0 || strcmp(pwd->pw_passwd, "*NP*") == 0) { if((spwd = getspnam(name)) == NULL) { return(-1); } #if defined(M_UNIX) encrypted_pass = spwd->pw_passwd; #else encrypted_pass = spwd->sp_pwdp; #endif /* M_UNIX */ } #endif /* !NOSHADOW */ } /* Run encryption algorythm */ encpw = crypt(passwd, encrypted_pass); /* Check it */ if(strcmp(encpw, encrypted_pass)) { DEBUG("unix_pass: password for \"%s\"%s failed\n", name, from); return(-1); } return(0); } /************************************************************************* * * Function: unix_group * * Purpose: Check the user's membership to the standard UNIX * group table. * *************************************************************************/ int unix_group(name, group) char *name; char *group; { struct passwd *pwd; struct passwd *getownpwnam(); struct passwd *getpwnam(); char **gr_mem; struct group *gr_ent; /* Get encrypted password from alternate password file */ if (alt_passwd != (char *)NULL) { if((pwd = getownpwnam(name)) == NULL) { DEBUG("unix_group: getownpwnam for \"%s\" failed\n", name); return(-1); } } else { /* Get encrypted password from password file */ if((pwd = getpwnam(name)) == NULL) { DEBUG("unix_group: getpwnam for \"%s\" failed\n", name); return(0); } } if((gr_ent = getgrnam(group)) == NULL) { DEBUG("unix_group: getgrnam(%s) for \"%s\" failed\n", group,name); return(0); } /* Check the immediate group */ if(pwd->pw_gid == gr_ent->gr_gid) { return(1); } /* Search for this user */ gr_mem = gr_ent->gr_mem; while(*gr_mem != NULL) { if(strcmp(*gr_mem, name) == 0) { return(1); } gr_mem++; } return(0); } struct passwd * getownpwnam(name) char *name; { extern char *alt_passwd; extern char pwbuf[]; extern struct passwd pw; FILE *pwfd; char *ptr; if (alt_passwd == (char *)NULL) { return (struct passwd *)NULL; } if((pwfd = fopen(alt_passwd, "r")) == (FILE *)NULL) { return (struct passwd *)NULL; } memset((char *)&pw,0,sizeof(pw)); while(fgets(pwbuf, MAX_LINE_SIZE, pwfd) != (char *)NULL) { ptr = pwbuf; while (*ptr && *ptr != ':') ptr++; *ptr++ = '\0'; if (strcmp(name,pwbuf) == 0) { pw.pw_name = pwbuf; pw.pw_passwd = ptr; while (*ptr && *ptr != ':') ptr++; *ptr++ = '\0'; pw.pw_uid = atoi(ptr); while (*ptr && *ptr != ':') ptr++; *ptr++ = '\0'; pw.pw_gid = atoi(ptr); while (*ptr && *ptr != ':') ptr++; *ptr++ = '\0'; /* we do not use the rest of the entries */ return (&pw); } } return (struct passwd *)NULL; } radiusd-livingston-2.1/src/proxy.c0100644000175000017500000007373706734270171015160 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: proxy.c,v 1.2 1999/06/23 23:40:41 cdr Exp $ Copyright 1997-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" #include "users.h" extern char recv_buffer[4096]; extern char send_buffer[4096]; extern int sockfd; extern int acctfd; extern int proxyfd; extern int proxyacctfd; extern u_short radius_port; extern char *radius_dir; extern UINT4 now; char *ipaddr2strp(); char *req2strp(); void req2str(); static AUTH_REQ *first_forwarded = (AUTH_REQ *)NULL; static PEER *servers; static PEER *server_default; static PEER *server_norealm; /************************************************************************* ************************************************************************* Subroutines related to forwarding a Proxy reply from a server to the client: rad_proxy(fd) pop_proxy(authreq, pstate) send_proxy2client(fd, authreq, server, pstate) update_proxy() find_server() ************************************************************************* *************************************************************************/ /************************************************************************* * * Function: rad_proxy * * Purpose: Receive UDP Proxy server replies and forward to client * * Uses External: sockfd, acctfd * *************************************************************************/ void rad_proxy(fd) int fd; { extern AUTH_REQ *first_forwarded; extern int max_proxy_time; AUTH_HDR *auth; AUTH_REQ *authreq; AUTH_REQ *oldqp; AUTH_REQ *qp; AUTH_REQ *qpop; AUTH_REQ *pop_proxy(); AUTH_REQ *radrecv(); PEER *find_server_byaddr(); PEER *server; UINT4 host; char *ip_hostname(); char digest[AUTH_VECTOR_LEN]; char hold_digest[AUTH_VECTOR_LEN]; char *sentreqauth; int recvfrom(); int result; int secretlen; size_t salen; struct sockaddr_in *sin; struct sockaddr_in rad_saremote; u_short port; void hexdump(); void md5_calc(); void reqfree(); void send_proxy2client(); salen = sizeof(rad_saremote); sin = (struct sockaddr_in *) & rad_saremote; auth = (AUTH_HDR *)recv_buffer; result = recvfrom (fd, (char *) recv_buffer, (int) sizeof(recv_buffer), (int) 0, (struct sockaddr *)&rad_saremote, &salen); host = ntohl(sin->sin_addr.s_addr); port = ntohs(sin->sin_port); /* Drop the packet if we do not know the proxy */ if ((server = find_server_byaddr(host, port)) == (PEER *)NULL) { log_err("auth: packet from unknown proxy server %s.%d ignored\n", ipaddr2strp(host), port); return; } authreq = radrecv( host, port, server->secret, recv_buffer, result); if (authreq == (AUTH_REQ *)NULL) { return; } /* Verify response authenticator */ switch (authreq->code) { case PW_AUTHENTICATION_ACK: case PW_AUTHENTICATION_REJECT: case PW_ACCESS_CHALLENGE: fd = sockfd; break; case PW_ACCOUNTING_RESPONSE: fd = acctfd; break; case PW_AUTHENTICATION_REQUEST: case PW_ACCOUNTING_REQUEST: default: log_err("rad_proxy: proxy server %s/%d.%d sent back invalid packet type %d, ignoring\n", ipaddr2strp(host), port, authreq->id, authreq->code); reqfree(authreq, "rad_proxy"); return; break; } DEBUG("proxy server %s/%d.%d replied with code=%d, length=%d\n", ipaddr2strp(host), port, authreq->id, authreq->code, result); if (debug_flag > 2) { hexdump(recv_buffer,result); } /* Find original request authenticator */ oldqp = (AUTH_REQ *)NULL; qp = first_forwarded; while ((qp != (AUTH_REQ *)NULL) && (qp->forw_id != authreq->id)) { oldqp = qp; if (qp == qp->next) { /* should never happen */ log_err("ERROR: circular queue detected at %d\n", __LINE__); qp->next = (AUTH_REQ *)NULL; } qp = qp->next; } if (qp != (AUTH_REQ *)NULL) { if (oldqp == (AUTH_REQ *)NULL) { first_forwarded = qp->next; } else { oldqp->next = qp->next; } qp->next = (AUTH_REQ *)NULL; sentreqauth = qp->forw_vector; } qpop = (AUTH_REQ *)NULL; if (server->flags & PEER_NOPROXY) { /* server can't do proxy */ if (qp == (AUTH_REQ *)NULL) { /* not found in queue */ DEBUG("rad_proxy: response from %s/%d.%d not matched in forwarded queue, dropped\n", ipaddr2strp(host), port, authreq->id); reqfree(authreq, "rad_proxy"); return; } else { qpop = qp; } } else { /* proxy-capable server */ /* pop last Proxy-State and fill in qp, if needed */ if ((qpop = pop_proxy(authreq, qp)) == (AUTH_REQ *)NULL) { log_err("rad_proxy: invalid Proxy-State from proxy server %s/%d.%d, dropped\n", ipaddr2strp(host), port, authreq->id); if (debug_flag > 0) { hexdump(authreq->packet,result); } reqfree(authreq, "rad_proxy"); return; } } if (qp == (AUTH_REQ *)NULL) { if (authreq->code == PW_ACCOUNTING_RESPONSE) { /* radiusd has restarted or we've already forwarded this response, so drop this response */ DEBUG("rad_proxy: accounting-response from %s/%d.%d not matched in forwarded queue, dropped\n", ipaddr2strp(host), port, authreq->id); reqfree(authreq, "rad_proxy"); reqfree(qpop, "rad_proxy"); return; } else { /* for access-responses, we can use the Request * authenticator we included in the proxy, if we * do not find it in our queue */ qp = qpop; sentreqauth = qp->vector; } } if ((authreq->code == PW_ACCOUNTING_RESPONSE) && (server->flags & PEER_OLDACCT)) { /* ignore acct signature */ send_proxy2client(fd, authreq, server, qp); reqfree(qp,"rad_proxy"); } else { /* Check response authenticator */ memcpy(hold_digest, auth->vector, AUTH_VECTOR_LEN); memcpy(auth->vector, sentreqauth, AUTH_VECTOR_LEN); secretlen = strlen(server->secret); memcpy(recv_buffer + result, server->secret, secretlen); md5_calc(digest, (char *)auth, result + secretlen); memset(recv_buffer + result, 0, secretlen); /* no need to restore auth->vector */ if (memcmp(hold_digest, digest, AUTH_VECTOR_LEN) == 0) { send_proxy2client(fd, authreq, server, qp); reqfree(qp,"rad_proxy"); } else { log_err("rad_proxy: remote server %s/%d.%d sent invalid reply, dropping\n", ipaddr2strp(host), port, authreq->id); if (debug_flag > 0) { hexdump(authreq->packet,result); } /* requeue qp if it hasn't timed out */ if (qp != (AUTH_REQ *)NULL) { if (qp->timestamp + max_proxy_time > now) { qp->next = first_forwarded; first_forwarded = qp; } else { reqfree(qp,"rad_proxy"); } } } } reqfree(authreq,"rad_proxy"); return; } /************************************************************************* * * Function: pop_proxy * * Purpose: Remove the last proxy-state attribute from authreq->request, * and returns a pointer to qp, allocating it if necessary. * * Any format changes made here must also be made in push_proxy() * *************************************************************************/ AUTH_REQ * pop_proxy(authreq, qp) AUTH_REQ *authreq; AUTH_REQ *qp; { AUTH_REQ *reqalloc(); VALUE_PAIR *value_list; VALUE_PAIR *old_value; VALUE_PAIR *prev_value; VALUE_PAIR *lastproxy; UINT4 tmp; int find_client(); u_short tmps; u_char hostnm[256]; /* passed as an argument, but unused */ void pairfree(); old_value = (VALUE_PAIR *) NULL; prev_value = (VALUE_PAIR *) NULL; lastproxy = (VALUE_PAIR *) NULL; value_list = authreq->request; while(value_list != (VALUE_PAIR *)NULL) { if(value_list->attribute == PW_PROXY) { lastproxy = value_list; prev_value = old_value; } old_value = value_list; value_list = value_list->next; } if (lastproxy == (VALUE_PAIR *)NULL) { /* not found */ return (qp); } /* pop lastproxy from linked list */ if (prev_value != (VALUE_PAIR *)NULL) { prev_value->next = lastproxy->next; } else { authreq->request = lastproxy->next; } lastproxy->next = (VALUE_PAIR *)NULL; /* Proxy-State contains: Timestamp, Client, Port, Id in network order, a pad byte, and 16 octets of Request Authenticator */ if (lastproxy->lvalue < 28) { log_err("pop_proxy: Proxy-State from %s has too short length %d < 28, ignoring\n", req2strp(authreq), lastproxy->lvalue); } if (qp != (AUTH_REQ *)NULL) { pairfree(lastproxy, "pop_proxy"); return (qp); } else { qp = reqalloc("pop_proxy"); } memcpy((char *)&tmp, lastproxy->strvalue, 4); qp->timestamp = ntohl(tmp); memcpy((char *)&tmp, lastproxy->strvalue+4, 4); qp->ipaddr = ntohl(tmp); memcpy((char *)&tmps, lastproxy->strvalue+8, 2); qp->udp_port = ntohs(tmps); memcpy((char *)&(qp->id), lastproxy->strvalue+10, 1); memcpy((char *)qp->vector, lastproxy->strvalue+12, AUTH_VECTOR_LEN); pairfree(lastproxy, "pop_proxy"); if(find_client(qp->ipaddr, qp->secret, hostnm) != 0) { reqfree(qp, "pop_proxy"); qp = (AUTH_REQ *)NULL; } return qp; } /************************************************************************* * * Function: send_proxy2client * * Purpose: Forward a proxy reply to a client defined in qp. * Calling routine has already removed our Proxy-State * *************************************************************************/ void send_proxy2client(fd, authreq, server, qp) int fd; AUTH_REQ *authreq; PEER *server; AUTH_REQ *qp; { AUTH_HDR *auth; VALUE_PAIR *curpair; VALUE_PAIR *get_attribute(); VALUE_PAIR *pair; VALUE_PAIR *reply; char ip_str[32]; int build_packet(); u_short total_length; void ipaddr2str(); void pairfree(); void send_packet(); auth = (AUTH_HDR *)send_buffer; reply = authreq->request; req2str(ip_str, authreq); /* if realm is marked insecure and has returned a Admin or NAS-Prompt service type, send a reject to the client instead, and log it */ if ( (!(server->flags & PEER_ADMINOK)) && (((pair = get_attribute(authreq->request, PW_USER_SERVICE_TYPE)) != (VALUE_PAIR *)NULL) && ((pair->lvalue == PW_ADMIN_USER) || (pair->lvalue == PW_PROMPT_USER)))) { authreq->code = PW_AUTHENTICATION_REJECT; log_err("remote server %s returned insecure service for client %s, sending reject instead\n", ip_str, req2strp(qp)); /* copy over only proxy-states */ authreq->request = (VALUE_PAIR *)NULL; curpair = (VALUE_PAIR *)NULL; while(reply != (VALUE_PAIR *)NULL) { if (reply->attribute == PW_PROXY) { if (curpair == (VALUE_PAIR *)NULL) { curpair = reply; authreq->request = reply; } else { curpair->next = reply; curpair = reply; } } else { pairfree(reply, "send_proxy2client"); } reply=reply->next; } if (curpair != (VALUE_PAIR *)NULL) { curpair->next = (VALUE_PAIR *)NULL; } } DEBUG("forwarding reply code %d from %s to %s\n", authreq->code, ip_str, req2strp(qp)); /* Load up the configuration values for the user */ total_length = build_packet(qp, authreq->request, (char *)NULL, authreq->code, FW_CLIENT, send_buffer); /* send it to the client */ send_packet(fd, qp->ipaddr, qp->udp_port, send_buffer, total_length); } /************************************************************************* * * Function: update_proxy * * Purpose: Check last modified time on proxy file and build a * new servers list if the file has been changed. * *************************************************************************/ int update_proxy() { extern u_short radacct_port; extern u_short radius_port; static UINT4 ouraddress = 0; static int first = 0; static time_t last_update_time; FILE *fd; PEER *curserv; PEER *peeralloc(); PEER *server; UINT4 get_ipaddr(); UINT4 ipaddr; char *arg; char *hostnm; char *realm; char *secret; char *strtok(); char ourname[256]; int gethostname(); int lineno; int nproxy; struct stat statbuf; u_char buffer[256]; u_short rport; void peerfree(); int fclose(); nproxy = 0; /* Check last modified time of proxy file */ sprintf((char *)buffer, "%s/%s", radius_dir, RADIUS_PROXY); if(stat(buffer, &statbuf) != 0) { if (first == 0) { log_err("proxy file %s not found; not using proxy\n", buffer); first++; } return(0); } if(statbuf.st_mtime == last_update_time) { /* nothing to update */ return(0); } /* Get our address if we have not already */ /* This will need to be changed to support multi-homed hosts */ if (ouraddress == 0) { errno = 0; if (gethostname(ourname, 128) != 0) { log_err("update_proxy: unable to get own hostname; %s\n", sys_errlist[errno]); } ouraddress = get_ipaddr(ourname); if (ouraddress == 0) { log_err("update_proxy: unable to resolve own hostname \"%s\"\n",ourname); } } /* Proxy file format: * hostname secret realm options... * * realm can be user@realm or a Called-Station-Id * */ /* Open the proxy file */ if((fd = fopen((const char *)buffer, "r")) == (FILE *)NULL) { log_err("Error: could not read proxy file %s; %s\n", buffer, sys_errlist[errno]); return(-1); } /* free up existing linked list of servers */ while (servers != (PEER *)NULL) { server = servers; servers = servers->next; server->next = (PEER *)NULL; peerfree(server, "update_proxy"); } server = (PEER *)NULL; server_default = (PEER *)NULL; server_norealm = (PEER *)NULL; lineno=0; while (fgets((char *)buffer, sizeof(buffer), fd) != (char *)NULL) { lineno++; if(*buffer == '#' || *buffer == ' ' || *buffer == '\t' || *buffer == '\n') { continue; } hostnm = strtok(buffer, " \t\n"); secret = strtok((char *)NULL, " \t\n"); realm = strtok((char *)NULL, " \t\n"); if (realm == (char *)NULL) { log_err("syntax error on line %d in proxy file\n", lineno); continue; } if((ipaddr = get_ipaddr(hostnm)) == (UINT4)0) { log_err("could not resolve proxy hostname %s at line %d\n", hostnm, lineno); continue; } /* store in realm linked list */ server = peeralloc("update_proxy"); /* parse arguments to proxy line */ while ((arg = strtok((char *)NULL, " \t\n, ")) != (char *)NULL) { if (isdigit(arg[0])) { rport = atoi(arg); if (rport > 0 && rport <= 0xffff) { if (server->radport == 0) { server->radport = rport; } else if (server->acctport == 0) { server->acctport = rport; } else { log_err("unknown argument \"%s\" on line %d in proxy file\n", arg, lineno); } } continue; } if (strcmp(arg, "old") == 0) { server->flags |= PEER_NOPROXY; server->flags |= PEER_OLDACCT; } else if (strcmp(arg, "secure") == 0) { server->flags |= PEER_ADMINOK; } else if (strcmp(arg, "ipass") == 0) { server->flags |= PEER_IPASS; } else { log_err("unknown argument \"%s\" on line %d in proxy file ignored\n", arg, lineno); } } if (server->radport == 0) { server->radport = radius_port; } if (server->acctport == 0) { server->acctport = radacct_port; } if ((ipaddr == ouraddress) && ((server->radport == radius_port) || (server->acctport == radacct_port))) { ipaddr = 0; /* handle ourselves, do not forward */ } server->ipaddr = ipaddr; memcpy(server->secret, secret, strlen(secret)); memcpy(server->realm, realm, strlen(realm)); if (strcmp(realm, "DEFAULT") == 0) { server_default = server; } else if (strcmp(realm, "NOREALM") == 0) { server_norealm = server; } if (servers == (PEER *)NULL) { /* first one */ servers = server; curserv = server; } else { curserv->next = server; curserv = server; } nproxy++; } fclose(fd); last_update_time = statbuf.st_mtime; DEBUG("found %d proxy realms\n", nproxy); return(0); } /************************************************************************* ************************************************************************* Subroutines related to forwarding a Proxy request from a client to the appropriate server handle_proxy(authreq) push_proxy(authreq) find_server(number, realm) find_server_byaddr(ipaddr, port) send_proxy2server(authreq, server) getnextid(authreq) ************************************************************************* *************************************************************************/ /************************************************************************* * * Function: handle_proxy * * Purpose: Called by rad_request() to check if access-request should * be forwarded to another server. * Called by rad_acctreq() to forward acct-request if needed. * * Returns: * -1 on error * 0 if this request was not forwarded * 1 if this request was forwarded * Side-Effects: * Sets REQ_PROXY flag in authreq if request was forwarded * * *************************************************************************/ int handle_proxy(authreq) AUTH_REQ *authreq; { AUTH_REQ *radrecv(); PEER *find_server(); PEER *server; VALUE_PAIR *get_attribute(); VALUE_PAIR *namepair; VALUE_PAIR *pair; char *decrypt_password(); char *encrypt_password(); char *name; char namebuf[256]; char *number; char *ptr; char *realm; char *strchr(); int rad_forw_ipass(); int ret; void push_proxy(); void send_proxy2server(); realm = (char *)NULL; number = (char *)NULL; namebuf[0] = '\0'; name = namebuf; if (authreq == (AUTH_REQ *)NULL) { return -1; } if (authreq->code != PW_AUTHENTICATION_REQUEST && authreq->code != PW_ACCOUNTING_REQUEST) { /* should not happen unless client sent bogus message */ DEBUG("handle_proxy called for packet type %d unexpectedly\n", authreq->code); authreq->flags |= REQ_ERR|REQ_FREE; return -1; } namepair = get_attribute(authreq->request, PW_USER_NAME); if (namepair != (VALUE_PAIR *)NULL) { memcpy(namebuf, namepair->strvalue, namepair->lvalue); namebuf[namepair->lvalue] = '\0'; if ((realm=strchr((const char *)name, '@')) != (char *)NULL) { *realm = '\0'; realm++; } else if ((ptr=strchr((const char *)name, '/')) != (char *)NULL) { *ptr = '\0'; ptr++; realm = name; name = ptr; } else { realm = (char *)NULL; } } pair = get_attribute(authreq->request, PW_CALLED); if (pair != (VALUE_PAIR *)NULL) { number = pair->strvalue; } /* look up number or realm in the list of servers. If a proxy * is found, parse the packet, unencrypt the password if * any, re-encrypt the password (if any), attach a * proxy-state with push_proxy(), and forward it to the proxy. * Use the same Request Authenticator (in case of CHAP) but * use a new Id */ if ((server = find_server(number, realm)) == (PEER *)NULL) { if (namepair != (VALUE_PAIR *)NULL) { strncpy(authreq->name, namepair->strvalue, 64); authreq->name[63] = '\0'; } else { authreq->name[0] = '\0'; } return 0; /* no proxy */ } strncpy(authreq->realm, server->realm, 64); strncpy(authreq->name, name, 64); authreq->name[63] = '\0'; if (server->ipaddr == 0) { /* this is the server for this realm */ return 0; } authreq->flags |= REQ_PROXY; if (server->flags & PEER_IPASS) { if (authreq->code == PW_AUTHENTICATION_REQUEST) { ret = rad_forw_ipass(authreq, sockfd, authreq->packet); authreq->flags |= REQ_FREE; return ret; } else if (authreq->code == PW_ACCOUNTING_REQUEST) { ret = rad_forw_ipass(authreq, acctfd, authreq->packet); authreq->flags |= REQ_FREE; return 0; } else { authreq->flags |= REQ_ERR|REQ_FREE; return -1; } } if (authreq->code == PW_AUTHENTICATION_REQUEST) { if (decrypt_password(authreq, authreq->secret) != (char *)NULL) { encrypt_password(authreq, server->secret); } } /* If remote server cannot handle proxy, delete realm from User-Name */ if ( server->flags & PEER_NOPROXY ) { if (namepair != (VALUE_PAIR *)NULL) { strcpy(namepair->strvalue,name); namepair->lvalue = strlen(name); } } else { push_proxy(authreq); } send_proxy2server(authreq, server); return 1; } /************************************************************************* * * Function: push_proxy * * Purpose: Adds a Proxy-State to the end of a packet * Note that RADIUS requires that Proxy-State always be * added after any existing Proxy-State attributes. * * Any changes made here must also be made in pop_proxy() * *************************************************************************/ void push_proxy(authreq) AUTH_REQ *authreq; { DICT_ATTR *attr; DICT_ATTR *dict_attrget(); VALUE_PAIR *pair; VALUE_PAIR *list; VALUE_PAIR *pairalloc(); UINT4 tmp; u_short tmps; void rad_exit(); pair = pairalloc("push_proxy"); /* Proxy-State contains: Timestamp, Client, Port, Id in network order, a pad byte, and 16 octets of Request Authenticator */ if((attr = dict_attrget(PW_PROXY)) == (DICT_ATTR *)NULL) { DEBUG("add Proxy (%d) to dictionary\n", PW_PROXY); strcpy(pair->name, "Proxy"); pair->type = PW_TYPE_STRING; } else { strcpy(pair->name, attr->name); pair->type = attr->type; } pair->attribute = PW_PROXY; pair->lvalue = 28; /* length of data */ tmp = htonl(authreq->timestamp); memcpy(pair->strvalue, (char *)&tmp, 4); tmp = htonl(authreq->ipaddr); memcpy(pair->strvalue+4, (char *)&tmp, 4); tmps = htons(authreq->udp_port); memcpy(pair->strvalue+8, (char *)&tmps, 2); memcpy(pair->strvalue+10, (char *)&(authreq->id), 1); memset(pair->strvalue+11, 0, 1); /* zero pad */ memcpy(pair->strvalue+12, authreq->vector, AUTH_VECTOR_LEN); if ((list = authreq->request) == (VALUE_PAIR *)NULL) { authreq->request = pair; } else { while(list->next != (VALUE_PAIR *)NULL) { list = list->next; } list->next = pair; } } /************************************************************************* * * Function: find_server * * Purpose: Returns server to forward to based on number or realm * Number takes precedence * *************************************************************************/ PEER * find_server(number, realm) char *number; char *realm; { extern PEER *servers; extern PEER *server_default; extern PEER *server_norealm; PEER *server; PEER *maybe; maybe = (PEER *)NULL; server=servers; /* In a future version we may want to match with or without area code */ while(server != (PEER *)NULL) { if ((number != (char *)NULL) && (strcmp(server->realm, number) == 0)) { return server; } if ((realm != (char *)NULL) && (strcmp(server->realm, realm) == 0)) { maybe = server; } server = server->next; } if (maybe == (PEER *)NULL) { if (realm != (char *)NULL) { maybe = server_default; } else { maybe = server_norealm; } } return maybe; } /************************************************************************* * * Function: find_server_byaddr * * Purpose: Returns proxy server based on IP address and source port * *************************************************************************/ PEER * find_server_byaddr(ipaddr, port) UINT4 ipaddr; u_short port; { PEER *server; extern PEER *servers; server=servers; while ((server != (PEER *)NULL) && !((server->ipaddr == ipaddr) && ((server->acctport == port) || (server->radport == port))) ) { server = server->next; } return server; } /************************************************************************* * * Function: send_proxy2server * * Purpose: Forward a proxy request to a server * Calling routine has already encrypted password (if any) * and added our Proxy-State * *************************************************************************/ void send_proxy2server(authreq, server) AUTH_REQ *authreq; PEER *server; { extern AUTH_REQ *first_forwarded; AUTH_HDR *auth; char *bufalloc(); char ip_str[32]; int build_packet(); int fd; u_char getnextid(); u_char saveid; u_short total_length; void md5_calc(); void send_packet(); req2str(ip_str, authreq); auth = (AUTH_HDR *)send_buffer; if (authreq->code == PW_AUTHENTICATION_REQUEST) { authreq->forw_port = server->radport; fd = proxyfd; } else if (authreq->code == PW_ACCOUNTING_REQUEST) { authreq->forw_port = server->acctport; fd = proxyacctfd; } else { log_err("unknown request type %d from %s ignored\n", authreq->code, ip_str); authreq->flags |= REQ_ERR|REQ_FREE; return; } authreq->forw_id = getnextid(authreq); /* getnextid sets REQ_ERR flag if unable to allocate id */ if ((authreq->flags & REQ_ERR) == REQ_ERR) { return; } saveid = authreq->id; authreq->id = authreq->forw_id; authreq->forw_addr = server->ipaddr; memcpy(authreq->forw_vector, authreq->vector, AUTH_VECTOR_LEN); strcpy(authreq->forw_secret, server->secret); DEBUG("forwarding request from %s to %s/%d.%d for %s\n", ip_str, ipaddr2strp(authreq->forw_addr), authreq->forw_port, authreq->forw_id, authreq->realm); total_length = build_packet(authreq, authreq->request, (char *)NULL, authreq->code, FW_SERVER, send_buffer); authreq->id = saveid; memcpy(authreq->forw_vector, auth->vector, AUTH_VECTOR_LEN); /* forward it to the server */ send_packet(fd, authreq->forw_addr, authreq->forw_port, send_buffer, total_length); if (!(authreq->flags & REQ_DUP)) { authreq->next = first_forwarded; first_forwarded = authreq; if (authreq == authreq->next) { log_err("ERROR: circular queue detected at %d\n", __LINE__); } } return; } /************************************************************************* * * Function: getnextid * * Purpose: Returns next ID for use in forwarding to this server * Use one ID counter 0..255 for all forwarded packets * *************************************************************************/ u_char getnextid(authreq) AUTH_REQ *authreq; { extern AUTH_REQ *first_forwarded; AUTH_REQ *qp; AUTH_REQ *prevqp; static char inuse[256]; u_char newid; static u_char curid = 0; static int flushcount = 0; extern int max_proxy_time; extern UINT4 now; memset(inuse, 0, 256); prevqp = (AUTH_REQ *)NULL; qp = first_forwarded; while (qp != (AUTH_REQ *)NULL) { if (qp->timestamp + max_proxy_time < now) { if (++flushcount % 100 == 0) { DEBUG("%d proxy requests expired unanswered\n",flushcount); } if (prevqp == (AUTH_REQ *)NULL) { first_forwarded = qp->next; reqfree(qp,"getnextid"); qp = first_forwarded; } else { prevqp->next = qp->next; reqfree(qp,"getnextid"); qp = prevqp->next; } } else { if (authreq->ipaddr == qp->ipaddr && authreq->udp_port == qp->udp_port && authreq->id == qp->id) { authreq->flags |= REQ_DUP|REQ_FREE; return qp->forw_id; } inuse[qp->forw_id]++; if (qp == qp->next) { log_err("ERROR: circular queue detected at %d\n", __LINE__); qp->next = (AUTH_REQ *)NULL; } prevqp = qp; qp = qp->next; } } for (newid = curid; newid < 256; newid++) { if (inuse[newid] == 0) { curid = ((newid+1) & 0xff); return newid; } } for (newid = 0; newid < curid; newid++) { if (inuse[newid] == 0) { curid = ((newid+1) & 0xff); return newid; } } /* no ids left, so log an error and mark packet for discard */ log_err("getnextid: out of IDs, dropping packet from %s\n", req2strp(authreq)); authreq->flags |= REQ_ERR|REQ_FREE; return 0; } /************************************************************************* ************************************************************************* Misc subroutines for proxy ************************************************************************* *************************************************************************/ /************************************************************************* * * Function: proxy_report * * Purpose: Log proxy queue status for debugging purposes * * Uses External: first_forwarded * *************************************************************************/ void proxy_report() { AUTH_REQ *qp; UINT4 oldest; UINT4 clock; int n; time_t time(); if (first_forwarded != (AUTH_REQ *)NULL) { qp = first_forwarded; n = 0; clock = (UINT4)time((time_t *)NULL); oldest = clock; while (qp != (AUTH_REQ *)NULL) { n++; if (qp->timestamp < oldest) { oldest = qp->timestamp; } qp = qp->next; } clock = clock - oldest; log_err("%d in proxy queue, oldest %d seconds ago\n", n, clock); } else { log_err("no entries in proxy queue\n"); } } radiusd-livingston-2.1/src/radius.h0100644000175000017500000002152706734270171015261 0ustar pmpm/************************************************************************ RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /* * $Id: radius.h,v 1.20 1999/06/23 23:40:41 cdr Exp $ */ #include "conf.h" #define AUTH_VECTOR_LEN 16 #define AUTH_PASS_LEN 16 #define AUTH_MAXPASS_LEN 48 #define AUTH_STRING_LEN 253 /* maximum of 253 */ #define MAX_LINE_SIZE 256 #define MAX_HOST_SIZE 128 typedef struct pw_auth_hdr { u_char code; u_char id; u_short length; char vector[AUTH_VECTOR_LEN]; u_char data[2]; } AUTH_HDR; #define AUTH_HDR_LEN 20 #define CHAP_VALUE_LENGTH 16 #define PW_AUTH_UDP_PORT 1645 #define PW_ACCT_UDP_PORT 1646 #define PW_PROXY_UDP_PORT 1815 #define PW_PROXYACCT_UDP_PORT 1816 #define PW_TYPE_STRING 0 #define PW_TYPE_INTEGER 1 #define PW_TYPE_IPADDR 2 #define PW_TYPE_DATE 3 #define PW_AUTHENTICATION_REQUEST 1 #define PW_AUTHENTICATION_ACK 2 #define PW_AUTHENTICATION_REJECT 3 #define PW_ACCOUNTING_REQUEST 4 #define PW_ACCOUNTING_RESPONSE 5 #ifdef PASSCHANGE #define PW_PASSWORD_REQUEST 7 #define PW_PASSWORD_ACK 8 #define PW_PASSWORD_REJECT 9 #endif /* PASSCHANGE */ #define PW_ACCESS_CHALLENGE 11 #define PW_USER_NAME 1 #define PW_PASSWORD 2 #define PW_CHAP_PASSWORD 3 #define PW_CLIENT_ID 4 #define PW_CLIENT_PORT_ID 5 #define PW_USER_SERVICE_TYPE 6 #define PW_FRAMED_PROTOCOL 7 #define PW_FRAMED_ADDRESS 8 #define PW_FRAMED_NETMASK 9 #define PW_FRAMED_ROUTING 10 #define PW_FRAMED_FILTER_ID 11 #define PW_FRAMED_MTU 12 #define PW_FRAMED_COMPRESSION 13 #define PW_LOGIN_HOST 14 #define PW_LOGIN_SERVICE 15 #define PW_LOGIN_TCP_PORT 16 #ifdef PASSCHANGE #define PW_OLD_PASSWORD 17 #endif #define PW_PORT_MESSAGE 18 #define PW_DIALBACK_NO 19 #define PW_DIALBACK_NAME 20 #define PW_FRAMED_ROUTE 22 #define PW_FRAMED_IPXNET 23 #define PW_STATE 24 #define PW_VENDOR 26 #define PW_TERMINATION 29 #define PW_CALLED 30 #define PW_CALLING 31 #define PW_PROXY 33 #define PW_ACCT_STATUS_TYPE 40 #define PW_ACCT_DELAY_TIME 41 #define PW_ACCT_INPUT_OCTETS 42 #define PW_ACCT_OUTPUT_OCTETS 43 #define PW_ACCT_SESSION_ID 44 #define PW_ACCT_AUTHENTIC 45 #define PW_ACCT_SESSION_TIME 46 # #define PW_CHAP_CHALLENGE 60 #define PW_CONNECT_INFO 77 /* * Non-Protocol Attributes */ #define PW_EXPIRATION 21 #define PW_AUTHTYPE 1000 #define PW_MENU 1001 #define PW_TERMINATION_MENU 1002 #define PW_PREFIX 1003 #define PW_SUFFIX 1004 #define PW_GROUP 1005 #define PW_CRYPT_PASSWORD 1006 #define PW_CONNECT_RATE 1007 /* * INTEGER TRANSLATIONS */ /* USER TYPES */ #define PW_LOGIN_USER 1 #define PW_FRAMED_USER 2 #define PW_DIALBACK_LOGIN_USER 3 #define PW_DIALBACK_FRAMED_USER 4 #define PW_OUTBOUND_USER 5 #define PW_ADMIN_USER 6 #define PW_PROMPT_USER 7 #define PW_CALL_CHECK_USER 10 #define PW_OLD_CALL_CHECK_USER 129 /* FRAMED PROTOCOLS */ #define PW_PPP 1 #define PW_SLIP 2 /* FRAMED ROUTING VALUES */ #define PW_NONE 0 #define PW_BROADCAST 1 #define PW_LISTEN 2 #define PW_BROADCAST_LISTEN 3 /* FRAMED COMPRESSION TYPES */ #define PW_VAN_JACOBSON_TCP_IP 1 /* LOGIN SERVICES */ #define PW_TELNET 0 #define PW_RLOGIN 1 #define PW_TCP_CLEAR 2 #define PW_PORTMASTER 3 /* AUTHENTICATION LEVEL */ #define PW_AUTH_NONE 0 #define PW_AUTH_RADIUS 1 #define PW_AUTH_LOCAL 2 /* STATUS TYPES */ #define PW_STATUS_START 1 #define PW_STATUS_STOP 2 /* TERMINATION OPTIONS */ #define PW_TERM_DEFAULT 0 #define PW_TERM_RADIUS_REQUEST 1 /* Internal Authentication Types */ #define PW_AUTHTYPE_NONE -1 #define PW_AUTHTYPE_LOCAL 0 #define PW_AUTHTYPE_UNIX 1 #define PW_AUTHTYPE_SECURID 2 #define PW_AUTHTYPE_CRYPT 3 #define PW_AUTHTYPE_REJECT 4 #define PW_AUTHTYPE_ACTIVCARD 5 /* Proxy Flags */ #define PEER_NOPROXY 1 /* do not include Proxy-State */ #define PEER_OLDACCT 2 /* do not check sig on acct-response */ #define PEER_ADMINOK 4 /* allow admin logins by proxy */ #define PEER_IPASS 8 /* forward using ipass protocol */ /* AUTH_REQ Flags */ #define REQ_PROXY 1 /* packet was forwarded */ #define REQ_DUP 2 /* packet is a duplicate */ #define REQ_ERR 4 /* packet is in error */ #define REQ_FREE 8 /* packet can be freed */ /* build_packet Flags */ /* Report Indices */ #define FW_REPLY 0 /* reply to client */ #define FW_SERVER 1 /* forward to server */ #define FW_CLIENT 2 /* forward reply to client */ #define RR_PORT1 1 /* packets received on RADIUS port */ #define RR_PORT2 2 /* packets received on RADIUS accounting port */ #define RR_PORT3 3 /* packets received on RADIUS proxy port */ #define RR_PORT4 4 /* packets received on RADIUS acct proxy port */ #define RR_ACCEPT 5 /* access-accepts sent */ #define RR_REJECT 6 /* access-rejects sent */ #define RR_CHALLENGE 7 /* access-challenges sent */ #define RR_ACCOUNT 8 /* accounting-responses sent */ #define RR_MAX 20 /* Default Database File Names */ #define RADIUS_DIR "/etc/raddb" #define RADACCT_DIR "/usr/adm/radacct" #define RADIUS_DICTIONARY "dictionary" #define RADIUS_CLIENTS "clients" #define RADIUS_CLIENT_CACHE "clcache" #define RADIUS_PROXY "proxy" #define RADIUS_USERS "users" #ifdef VPORTS #define RADIUS_VPORTS "vports" #endif #ifdef PASSCHANGE #define RADIUS_HOLD "holdusers" #endif #ifdef ACTIVCARD #define ACTIVCARD_CONFIG "config.aeg" #endif /* Server data structures */ typedef struct dict_attr { char name[32]; int value; int type; int vendor; /* non-zero for Vendor-Specific */ int vsvalue; struct dict_attr *next; } DICT_ATTR; typedef struct dict_value { char attrname[32]; char name[32]; int value; struct dict_value *next; } DICT_VALUE; typedef struct value_pair { char name[32]; int attribute; int type; int vendor; int vsattribute; UINT4 lvalue; /* length of strvalue if present */ char strvalue[AUTH_STRING_LEN]; struct value_pair *next; } VALUE_PAIR; typedef struct auth_req { UINT4 ipaddr; u_short udp_port; u_char id; u_char code; char vector[AUTH_VECTOR_LEN]; char secret[20]; /* max length supported is 16 */ VALUE_PAIR *request; int child_pid; /* Process ID of child */ UINT4 timestamp; struct auth_req *next; /* Next active request */ UINT4 forw_addr; u_short forw_port; u_char forw_id; u_char flags; char forw_vector[AUTH_VECTOR_LEN]; char forw_secret[20]; char name[64]; char realm[64]; char *packet; } AUTH_REQ; typedef struct peer { UINT4 ipaddr; struct peer *next; u_short radport; u_short acctport; char realm[64]; char secret[20]; u_char id; u_char flags; } PEER; #define DEBUG if(debug_flag)log_debug #define SECONDS_PER_DAY 86400 #define CLEANUP_DELAY 5 #define MAX_REQUESTS 100 /* -q */ #if defined(SECURID) #define MAX_REQUEST_TIME 120 #else #define MAX_REQUEST_TIME 30 /* -t */ #endif #define MAX_PROXY_TIME 30 /* -w */ #define RADIUS_MSG_KEY(pid) (('r' << 24) + ((pid) & 0x00ffffff)) extern int debug_flag; extern void debug_pair (VALUE_PAIR * pair); void log_debug(), log_err(), pairfree(), reqfree(); radiusd-livingston-2.1/src/radiusd.c0100644000175000017500000021266706734270172015430 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /* don't look here for the version, run radiusd -v or look in version.c */ static char sccsid[] = "$Id: radiusd.c,v 1.46 1999/06/23 23:40:42 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" #include "users.h" #ifdef VPORTS #include "vports.h" #endif char recv_buffer[4096]; char send_buffer[4096]; char *progname; UINT4 sockaddr; int sockfd; int acctfd; int proxyfd; int proxyacctfd; int debug_flag; int debug_mem; int spawn_flag; int accept_zero; #ifdef VPORTS int vports_flag; #endif int acct_pid; int radius_dbm; int max_requests; int max_proxy_time; int max_request_time; char *alt_passwd; char *radius_dir; char *radacct_dir; char *radius_log; u_short radius_port; u_short radacct_port; u_short radproxy_port; u_short radpracct_port; UINT4 expiration_seconds; UINT4 now; UINT4 warning_seconds; extern int errno; static AUTH_REQ *first_request; int cleanup_pid; int report[RR_MAX]; char cached_hostnm[MAX_HOST_SIZE]; char unknown[8]; UINT4 cached_ipaddr; struct sockaddr_in rad_saremote; void sig_fatal(); void sig_hup(); void sig_cleanup(); void sig_usr1(); void sig_usr2(); void process_menu(); char *ipaddr2strp(); char *req2strp(); void md5_calc(); int main(argc, argv) int argc; char **argv; { UINT4 get_ipaddr(); UINT4 then; char argval; char argnum; int i; int t; int pid; fd_set readfds; int status; int atoi(); int config_init(); int dict_init(); int activcard_init(); int ipassinit(); int open_udpsock(); int update_clients(); int select(); int update_proxy(); int vports_init(); time_t time(); void log_version(); void rad_acctreq(); void rad_exit(); void rad_request(); void rad_proxy(); void usage(); void version(); progname = *argv++; argc--; sockaddr = 0; debug_flag = 0; debug_mem = 0; spawn_flag = 1; radius_dbm = 0; accept_zero = 0; max_requests = MAX_REQUESTS; max_request_time = MAX_REQUEST_TIME; max_proxy_time = MAX_PROXY_TIME; radacct_dir = RADACCT_DIR; radius_dir = RADIUS_DIR; alt_passwd = (char *)NULL; signal(SIGHUP, sig_hup); signal(SIGINT, sig_fatal); /* disable handler when debugging */ signal(SIGQUIT, sig_fatal); signal(SIGILL, sig_fatal); signal(SIGTRAP, sig_fatal); signal(SIGIOT, sig_fatal); signal(SIGFPE, sig_fatal); signal(SIGTERM, sig_fatal); signal(SIGCHLD, sig_cleanup); #if defined(SIGWINCH) signal(SIGWINCH, sig_hup); #endif signal(SIGUSR1, sig_usr1); signal(SIGUSR2, sig_usr2); for (i=0; i< RR_MAX; i++) { report[i] = 0; } while(argc) { if(**argv != '-') { usage(); } argval = *(*argv + 1); argnum = *(*argv + 2); argc--; argv++; switch(argval) { case 'a': if(argc == 0) { usage(); } radacct_dir = *argv; argc--; argv++; break; case 'b': /* use dbm users file */ radius_dbm = 1; break; case 'd': if(argc == 0) { usage(); } radius_dir = *argv; argc--; argv++; break; case 'f': if(argc == 0) { usage(); } alt_passwd = *argv; argc--; argv++; break; case 'h': usage(); break; case 'i': if(argc == 0) { usage(); } sockaddr = get_ipaddr(*argv); argc--; argv++; break; case 'l': /* change logging from syslog */ if(argc == 0) { usage(); } radius_log = *argv; argc--; argv++; break; case 'm': /* debug memory */ if (isdigit(argnum)) { debug_mem = argnum - '0'; } else { debug_mem++; } break; case 'p': /* set radius port */ if(argc == 0) { usage(); } radius_port = (u_short)atoi(*argv); argc--; argv++; break; case 'o': /* accept all-zero accounting request authenticators */ accept_zero = 1; break; case 'q': /* set max queue size */ if(argc == 0) { usage(); } max_requests = (int)atoi(*argv); argc--; argv++; break; case 's': /* Single process mode */ spawn_flag = 0; break; case 't': /* set max time out in seconds */ if(argc == 0) { usage(); } max_request_time = (int)atoi(*argv); argc--; argv++; break; case 'v': version(); break; case 'w': /* set proxy time in seconds */ if(argc == 0) { usage(); } max_proxy_time = (int)atoi(*argv); argc--; argv++; break; case 'x': if (isdigit(argnum)) { debug_flag = argnum - '0'; } else { debug_flag++; } break; case 'z': /* debugging: -b -s -x -d . -a ra */ radius_dbm = 1; spawn_flag = 0; debug_flag++; radius_dir = "."; radacct_dir = "ra"; break; default: usage(); break; } } if (debug_flag) { if (radius_log == (char *)NULL) { /* * for backward compatibility * send messages to users tty */ radius_log = "/dev/tty"; } else if (strcmp(radius_log, "syslog") == 0) { /* * allow user to override backward compatibility * and send debug to syslog */ radius_log = (char *)NULL; } } /* Initialize the dictionary */ if(dict_init() != 0) { rad_exit(-1); } /* Initialize Configuration Values */ if(config_init() != 0) { rad_exit(-1); } /* * Disconnect from session */ if(debug_flag == 0) { pid = fork(); if(pid < 0) { log_err("system error: could not fork at startup\n"); rad_exit(-1); } if(pid > 0) { exit(0); } } /* * Disconnect from tty */ for (t = 32; t >= 3; t--) { close(t); } /* Show our stuff */ log_version(); if (debug_flag) { log_err("debug mode %d\n",debug_flag); } if (debug_mem) { log_err("memory debug mode %d\n",debug_mem); } /* Open RADIUS socket */ sockfd = open_udpsock(&radius_port,PW_AUTH_UDP_PORT,"radius"); /* Open Accounting socket */ radacct_port = radius_port + 1; acctfd = open_udpsock(&radacct_port,PW_ACCT_UDP_PORT,"radacct"); /* * Open Proxy Socket. * We send to proxy servers from this socket, so replies return to it */ radproxy_port = radius_port + 5; radpracct_port = radius_port + 6; proxyfd = open_udpsock(&radproxy_port,PW_PROXY_UDP_PORT,"radius-proxy"); proxyacctfd = open_udpsock(&radpracct_port,PW_PROXYACCT_UDP_PORT,"radacct-proxy"); if (ipassinit() != 0) { log_err("ipass not in use\n"); } #ifdef ACTIVCARD /* establish aeg session before attending to any user requests */ if (activcard_init() < 0) { log_err("activcard not in use\n"); } #endif update_clients(); update_proxy(); #ifdef VPORTS vports_flag = vports_init(); if (vports_flag == 1 && spawn_flag == 1) { spawn_flag = 0; DEBUG("virtual ports disable spawning\n"); } #endif /* VPORTS */ /* * If we are able to spawn processes, we will start a child * to listen for Accounting-Requests. If not, we will * listen for them ourself. */ if(spawn_flag) { acct_pid = fork(); if(acct_pid < 0) { log_err("could not fork to spawn accounting daemon\n"); rad_exit(-1); } if(acct_pid > 0) { close(acctfd); acctfd = -1; close(proxyacctfd); proxyacctfd = -1; } else { close(sockfd); sockfd = -1; close(proxyfd); proxyfd = -1; } } then = 0; /* * Receive user requests */ for(;;) { FD_ZERO(&readfds); if(sockfd >= 0) { FD_SET(sockfd, &readfds); } if(proxyfd >= 0) { FD_SET(proxyfd, &readfds); } if(acctfd >= 0) { FD_SET(acctfd, &readfds); } if(proxyacctfd >= 0) { FD_SET(proxyacctfd, &readfds); } status = select(32, &readfds, NULL, NULL, (struct timeval *)NULL); if(status == -1) { if (errno == EINTR) continue; log_err("exiting after select returned error %d, %s\n",errno,sys_errlist[errno]); sig_fatal(101); } now = (UINT4)time((time_t *)NULL); if (now > then) { then = now; if(sockfd != -1) { update_clients(); } update_proxy(); } if(proxyfd >=0 && FD_ISSET(proxyfd, &readfds)) { rad_proxy(proxyfd); report[RR_PORT3]++; } if(sockfd >= 0 && FD_ISSET(sockfd, &readfds)) { rad_request(sockfd); report[RR_PORT1]++; } if(proxyacctfd >=0 && FD_ISSET(proxyacctfd, &readfds)) { rad_proxy(proxyacctfd); report[RR_PORT4]++; } if(acctfd >=0 && FD_ISSET(acctfd, &readfds)) { rad_acctreq(acctfd); report[RR_PORT2]++; } } } /************************************************************************* * * Function: open_udpsock * * Purpose: open desired UDP socket and return file descripter * Exit program if socket is unavailable * place port number used in first argument * *************************************************************************/ int open_udpsock(port,defport,service) u_short *port; int defport; char *service; { extern UINT4 sockaddr; int bind(); int fd; int result; int socket(); struct servent *svp; struct sockaddr_in *sin; struct sockaddr_in salocal; void rad_exit(); u_short lport; if (*port>5) { lport = htons(*port); } else { svp = getservbyname(service, "udp"); if (svp != (struct servent *) NULL) { lport = (u_short) svp->s_port; } else { lport = htons(defport); } *port = ntohs(lport); } DEBUG("using udp port %d for %s\n", *port,service); fd = socket (AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err("%s socket error %s\n", service, sys_errlist[errno]); rad_exit(-1); } sin = (struct sockaddr_in *) & salocal; memset ((char *) sin, '\0', sizeof (salocal)); sin->sin_family = AF_INET; if (sockaddr != 0) { sin->sin_addr.s_addr = htonl(sockaddr); } else { sin->sin_addr.s_addr = INADDR_ANY; } sin->sin_port = lport; result = bind (fd, (struct sockaddr *)&salocal, sizeof (*sin)); if (result < 0) { log_err("%s bind error %s\n", service, sys_errlist[errno]); rad_exit(-1); } return fd; } /************************************************************************* * * Function: send_packet * * Purpose: Send RADIUS UDP packet * *************************************************************************/ void send_packet(fd,ipaddr,port,buffer,length) int fd; UINT4 ipaddr; u_short port; char * buffer; int length; { AUTH_HDR *auth; int sendto(); struct sockaddr_in saremote; struct sockaddr_in *sin; void hexdump(); sin = (struct sockaddr_in *) &saremote; memset ((char *) sin, '\0', sizeof (saremote)); sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(ipaddr); sin->sin_port = htons(port); auth = (AUTH_HDR *)buffer; DEBUG("message sent to %s/%d.%d code=%d, length=%d\n", ipaddr2strp(ipaddr), port, auth->id, auth->code, length); if (debug_flag > 1) { hexdump(buffer,length); } /* Send it */ sendto(fd, buffer, (int)length, (int)0, (struct sockaddr *)&saremote, sizeof(struct sockaddr_in)); } /************************************************************************* * * Function: rad_request * * Purpose: Receive UDP client requests * *************************************************************************/ void rad_request(fd) int fd; { AUTH_REQ *authreq; AUTH_REQ *radrecv(); UINT4 addr; VALUE_PAIR *get_attribute(); char secret[20]; char hostnm[128]; int result; int find_client(); int handle_proxy(); int recvfrom(); size_t salen; struct sockaddr_in *sin; u_short port; void radrespond(); void reqfree(); #if defined(SMARTCARD) int child_pid; AUTH_HDR *auth; AUTH_REQ *curreq; VALUE_PAIR *pair; key_t msg_key; int msg_id; char *buf; int atoi(); #endif salen = sizeof (rad_saremote); sin = (struct sockaddr_in *) & rad_saremote; result = recvfrom (fd, (char *) recv_buffer, (int) sizeof(recv_buffer), (int) 0, (struct sockaddr *)&rad_saremote, &salen); addr = ntohl(sin->sin_addr.s_addr); port = ntohs(sin->sin_port); if (result < AUTH_HDR_LEN) { log_err("rad_request: runt packet of %d bytes from %s.%d\n", result,ipaddr2strp(addr),port); return; } /* * Validate the requesting IP address - * Not secure, but worth the check for accidental requests * find_client() logs an error message if needed */ if(find_client(addr, secret, hostnm) != 0) { log_err("rad_request: request from unknown client %s.%d ignored\n",ipaddr2strp(addr),port); return; } authreq = radrecv( addr, port, secret, recv_buffer, result ); if (authreq == (AUTH_REQ *)NULL) { /* malformed packet */ return; } /* handle_proxy places the user name in authreq->name, * and forwards request to a proxy server if necessary */ if (handle_proxy(authreq) != 0) { /* error or forwarded */ if (authreq->flags & REQ_FREE) { reqfree(authreq,"rad_request"); } /* otherwise authreq will be freed when proxy response is seen */ return; } #if defined(SMARTCARD) if (spawn_flag == 0) { radrespond(authreq, fd); return; } /* * We need to see if this is a challenge response */ child_pid = -1; if ((pair = get_attribute(authreq->request,PW_STATE)) != (VALUE_PAIR *)NULL) { buf = pair->strvalue; DEBUG("rad_request: PW_STATE<%s>\n", buf); #ifdef SECURID /* * the format for SECURID state string is * * SECURID_xxxx=n * * xxxx is commands: next or npin or wait * n is the child pid */ if (strncmp(buf, "SECURID_", 8) == 0) { child_pid = (int)atoi(&buf[13]); } #endif /* SECURID */ #ifdef ACTIVCARD /* * the format for ACTIVCARD state string is * * ACTIVCARD_999...=n * * 999... is the challenge returned by ActivEngine * n is the child pid */ if (strncmp(buf, "ACTIVCARD_", 10) == 0) { child_pid = (int)atoi(strchr(buf, (int)'=')+1); } #endif /* ACTIVCARD */ } if (child_pid == -1) { radrespond(authreq, fd); return; } DEBUG("rad_request: challenge_response from %s for child %d\n", req2strp(authreq), child_pid); curreq = first_request; while(curreq != (AUTH_REQ *)NULL) { if (curreq->child_pid == child_pid) { break; } curreq = curreq->next; } if (curreq == (AUTH_REQ *)NULL) { log_err("rad_request: child %d not found\n", child_pid); reqfree(authreq,"rad_request"); return; } if (curreq->ipaddr != addr) { log_err("rad_request: error: mismatched IP addresses in request %x != %x for ID %d %d\n", curreq->ipaddr, addr, curreq->id, auth->id); reqfree(authreq,"rad_request"); return; } if (curreq->udp_port != port) { log_err("rad_request: error: mismatched source ports in request %d != %d for ID %d %d\n", curreq->udp_port, port, curreq->id, auth->id); reqfree(authreq,"rad_request"); return; } if (curreq->id == authreq->id) { /* This is a duplicate request - just drop it */ log_err("rad_request: dropped duplicate ID %d\n", authreq->id); reqfree(authreq,"rad_request"); return; } msg_key = RADIUS_MSG_KEY(child_pid); if ((msg_id = msgget(msg_key, 0600)) == -1) { log_err("rad_request: error: msgget for key %x for id %d returned error %d\n",msg_key, msg_id, errno); reqfree(authreq,"rad_request"); return; } if (msgsnd(msg_id, recv_buffer, result, IPC_NOWAIT) == -1) { log_err("rad_request: error: msgsnd for key %x for id %d returned error %d\n", msg_key, msg_id, errno); reqfree(authreq,"rad_request"); return; } curreq->id = authreq->id; #else /* not SMARTCARD */ radrespond(authreq, fd); #endif /* not SMARTCARD */ } /************************************************************************* * * Function: radrecv * * Purpose: Receive UDP client requests, build an authorization request * structure, and attach attribute-value pairs contained in * the request to the new structure. * *************************************************************************/ AUTH_REQ * radrecv(host, udp_port, secret, buffer, length) UINT4 host; u_short udp_port; char *secret; u_char *buffer; int length; { u_char *ptr; char *bufalloc(); AUTH_HDR *auth; int totallen; int attribute; int attrlen; int vendor; int vsa; int vsattrlen; DICT_ATTR *attr; DICT_ATTR *dict_attrget(); DICT_ATTR *dict_vsattrget(); UINT4 lvalue; VALUE_PAIR *first_pair; VALUE_PAIR *prev; VALUE_PAIR *pair; VALUE_PAIR *pairalloc(); AUTH_REQ *authreq; AUTH_REQ *reqalloc(); void hexdump(); void pairfree(); void rad_exit(); void reqfree(); if (length < AUTH_HDR_LEN) { /* too short to be real */ log_err("radrecv: runt packet of %d bytes from %s/%d\n", length, ipaddr2strp(host), udp_port); return ((AUTH_REQ *)NULL); } /* * Pre-allocate the new request data structure */ authreq = reqalloc("radrecv"); auth = (AUTH_HDR *)buffer; totallen = ntohs(auth->length); if (totallen > length) { /* truncated packet, ignore */ log_err("radrecv: message from %s/%d claimed length %d, only %d bytes received\n", ipaddr2strp(host), udp_port, totallen, length); reqfree(authreq,"radrecv"); return((AUTH_REQ *)NULL); } DEBUG("message received from %s/%d.%d code=%d, length=%d\n", ipaddr2strp(host), udp_port, auth->id, auth->code, totallen); if (debug_flag > 1) { hexdump(buffer,totallen); } /* * Fill header fields */ authreq->ipaddr = host; authreq->udp_port = udp_port; authreq->id = auth->id; authreq->code = auth->code; memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN); strncpy(authreq->secret,secret,20); authreq->secret[19]='\0'; /* * Extract attribute-value pairs */ ptr = auth->data; length = totallen - AUTH_HDR_LEN; first_pair = (VALUE_PAIR *)NULL; prev = (VALUE_PAIR *)NULL; while(length > 0) { attribute = *ptr++; attrlen = *ptr++; if(attrlen < 2) { length = 0; continue; } attrlen -= 2; if ( attrlen > AUTH_STRING_LEN ) { log_err("radrecv: attribute %d from %s too long, length of %d > %d\n", attribute, req2strp(authreq), attrlen, AUTH_STRING_LEN); reqfree(authreq,"radrecv"); return((AUTH_REQ *)NULL); } pair = pairalloc("radrecv"); if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) { sprintf(pair->name,"Unknown-%d",attribute); pair->attribute = attribute; pair->type = PW_TYPE_STRING; } else { strcpy(pair->name, attr->name); pair->attribute = attr->value; pair->type = attr->type; } if (pair->attribute == PW_VENDOR) { if (attrlen < 6 || ((vsattrlen = *(ptr+5)) != (attrlen-4))) { pair->vendor = 0; pair->vsattribute = 0; pair->type = PW_TYPE_STRING; } else { memcpy(&vendor, ptr, sizeof(UINT4)); vendor = ntohl(vendor); ptr += 4; vsa = *ptr++; attrlen = vsattrlen - 2; ptr++; length -= 6; pair->vendor = vendor; pair->vsattribute = vsa; if((attr = dict_vsattrget(vendor,vsa)) != (DICT_ATTR *)NULL) { strcpy(pair->name, attr->name); pair->type = attr->type; } else { sprintf(pair->name,"Vendor-Specific-%d-%d",vendor,vsa); pair->type = PW_TYPE_STRING; } } } switch(pair->type) { case PW_TYPE_STRING: memcpy(pair->strvalue, ptr, attrlen); pair->strvalue[attrlen] = '\0'; pair->lvalue = attrlen; debug_pair(pair); if(first_pair == (VALUE_PAIR *)NULL) { first_pair = pair; } else { prev->next = pair; } prev = pair; break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: memcpy(&lvalue, ptr, sizeof(UINT4)); pair->lvalue = ntohl(lvalue); debug_pair(pair); if(first_pair == (VALUE_PAIR *)NULL) { first_pair = pair; } else { prev->next = pair; } prev = pair; break; default: DEBUG(" %s (Unknown Type %d)\n", attr->name,attr->type); pairfree(pair,"radrecv"); break; } ptr += attrlen; length -= attrlen + 2; } authreq->request = first_pair; authreq->timestamp = now; /* now was set in main() */ /* copy the packet */ authreq->packet = bufalloc(totallen,"radrecv"); memcpy(authreq->packet,buffer,totallen); return(authreq); } /************************************************************************* * * Function: radrespond * * Purpose: Respond to supported requests * * PW_AUTHENTICATION_REQUEST - Authentication request from * a client network access server. * * PW_PASSWORD_REQUEST - User request to change a password. * *************************************************************************/ void radrespond(authreq, activefd) AUTH_REQ *authreq; int activefd; { char *ip_hostname(); int rad_authenticate(); void rad_acctreq(); void rad_spawn_child(); #ifdef PASSCHANGE void rad_passchange(); #endif void reqfree(); if (authreq == (AUTH_REQ *)NULL) { return; } switch(authreq->code) { case PW_AUTHENTICATION_REQUEST: if(spawn_flag) { rad_spawn_child(authreq, activefd); } else { rad_authenticate(authreq, activefd); } break; #ifdef PASSCHANGE case PW_PASSWORD_REQUEST: rad_passchange(authreq, activefd); break; #endif default: log_err("unknown request type %d from %s ignored\n", authreq->code, req2strp(authreq)); reqfree(authreq,"radrespond"); break; } } /************************************************************************* * * Function: rad_spawn_child * * Purpose: Spawns child processes to perform password authentication * and respond to RADIUS clients. This functions also * cleans up complete child requests, and verifies that there * is only one process responding to each request (duplicate * requests are filtered out. * *************************************************************************/ int rad_spawned_child_pid; void rad_spawn_child(authreq, activefd) AUTH_REQ *authreq; int activefd; { AUTH_REQ *curreq; AUTH_REQ *prevreq; UINT4 curtime; int request_count; int child_pid; void child_authenticate(); void clean_child(); void pairfree(); void reqfree(); #ifdef SMARTCARD key_t msg_key; int msg_id; #endif curtime = authreq->timestamp; request_count = 0; curreq = first_request; prevreq = (AUTH_REQ *)NULL; while(curreq != (AUTH_REQ *)NULL) { if(curreq->child_pid == -1 && curreq->timestamp + CLEANUP_DELAY <= curtime) { /* Request completed, delete it */ if(prevreq == (AUTH_REQ *)NULL) { first_request = curreq->next; reqfree(curreq,"rad_spawn_child"); curreq = first_request; } else { prevreq->next = curreq->next; reqfree(curreq,"rad_spawn_child"); curreq = prevreq->next; } } else if(curreq->ipaddr == authreq->ipaddr && curreq->udp_port == authreq->udp_port && curreq->id == authreq->id) { /* This is a duplicate request - just drop it */ log_err("dropping duplicate request from %s\n", req2strp(authreq)); reqfree(authreq,"rad_spawn_child"); return; } else { if(curreq->timestamp + max_request_time <= curtime && curreq->child_pid != -1) { /* This request seems to have hung - kill it */ child_pid = curreq->child_pid; log_err("sending SIGHUP to unresponsive child process %d\n", child_pid); curreq->child_pid = -1; kill(child_pid, SIGHUP); #ifdef SMARTCARD /* * delete childs message queue */ msg_key = RADIUS_MSG_KEY(child_pid); if ((msg_id = msgget(msg_key, 0600)) != -1) { msgctl(msg_id, IPC_RMID, 0); } #endif /* SMARTCARD */ } prevreq = curreq; curreq = curreq->next; request_count++; } } /* This is a new request */ if(request_count > max_requests) { request_count--; log_err("dropping request from %s; %d requests already in queue\n", req2strp(authreq), request_count); reqfree(authreq,"rad_spawn_child"); return; } /* Add this request to the list */ /* authreq->timestamp already set by radrecv */ authreq->next = (AUTH_REQ *)NULL; authreq->child_pid = -1; if(prevreq == (AUTH_REQ *)NULL) { first_request = authreq; } else { prevreq->next = authreq; } /* fork our child */ cleanup_pid = -1; rad_spawned_child_pid = fork(); if(rad_spawned_child_pid < 0) { log_err("system error: fork failed with error %d for request from %s\n", errno,req2strp(authreq)); reqfree(authreq,"rad_spawn_child"); return; } if(rad_spawned_child_pid == 0) { /* This is the child, it should go ahead and respond */ child_authenticate(authreq, activefd); exit(0); } /* Register the Child */ authreq->child_pid = rad_spawned_child_pid; /* * If cleanup_pid is not -1, then we received a SIGCHLD between * the time we forked and the time we got here, so clean up after it */ if(cleanup_pid != -1) { clean_child(cleanup_pid); cleanup_pid = -1; } } void clean_child(pid) int pid; { AUTH_REQ *curreq; time_t time(); curreq = first_request; while(curreq != (AUTH_REQ *)NULL) { if(curreq->child_pid == pid) { curreq->child_pid = -1; curreq->timestamp = (UINT4)time((time_t *)NULL); return; } curreq = curreq->next; } cleanup_pid = (int)pid; return; } void sig_cleanup(sig) int sig; { int status; pid_t pid; for (;;) { pid = waitpid((pid_t)-1,&status,WNOHANG); signal(SIGCHLD, sig_cleanup); if (pid <= 0) return; #if defined (aix) kill(pid, SIGKILL); #endif if(pid == acct_pid) { sig_fatal(100); } clean_child(pid); } } #ifdef PASSCHANGE /************************************************************************* * * Function: rad_passchange * * Purpose: Change a users password * *************************************************************************/ void rad_passchange(authreq, activefd) AUTH_REQ *authreq; int activefd; { VALUE_PAIR *namepair; VALUE_PAIR *check_item; VALUE_PAIR *newpasspair; VALUE_PAIR *oldpasspair; VALUE_PAIR *curpass; VALUE_PAIR *user_check; VALUE_PAIR *user_reply; VALUE_PAIR *get_attribute(); USER_DESC *user_desc; char pw_digest[16]; char string[64]; char passbuf[AUTH_PASS_LEN]; char auth_name[AUTH_STRING_LEN + 2]; int i; int secretlen; char *ip_hostname(); int user_update(); int set_expiration(); void send_pwack(); void send_reject(); void pairfree(); void reqfree(); /* Get the username */ namepair = get_attribute(authreq->request,PW_USER_NAME); if(namepair == (VALUE_PAIR *)NULL) { log_err("passchange: from %s - no user name supplied\n", ipaddr2strp(authreq->ipaddr)); reqfree(authreq,"rad_passchange"); return; } /* * Open the user table */ if((user_desc = user_open()) == (USER_DESC *)NULL) { /* error already logged by user_open() */ reqfree(authreq,"rad_passchange"); return; } /* * Look the user up in the database */ if (user_find( namepair->strvalue, auth_name, &user_check, &user_reply, user_desc) != 0) { log_err("rad_passchange: from %s - user %s not found\n", ipaddr2strp(authreq->ipaddr), namepair->strvalue); send_reject(authreq, (char *)NULL, activefd); reqfree(authreq,"rad_passchange"); user_close(user_desc); return; } user_close(user_desc); /* * Validate the user - * * We have to unwrap this in a special way to decrypt the * old and new passwords. The MD5 calculation is based * on the old password. The vector is different. The old * password is encrypted using the encrypted new password * as its vector. The new password is encrypted using the * random encryption vector in the request header. */ /* Extract the attr-value pairs for the old and new passwords */ check_item = authreq->request; while(check_item != (VALUE_PAIR *)NULL) { if(check_item->attribute == PW_PASSWORD) { newpasspair = check_item; } else if(check_item->attribute == PW_OLD_PASSWORD) { oldpasspair = check_item; } check_item = check_item->next; } /* Verify that both encrypted passwords were supplied */ if(newpasspair == (VALUE_PAIR *)NULL || oldpasspair == (VALUE_PAIR *)NULL) { /* Missing one of the passwords */ log_err("rad_passchange: from %s - missing password in request for user %s\n", ipaddr2strp(authreq->ipaddr), namepair->strvalue); send_reject(authreq, (char *)NULL, activefd); pairfree(user_check,"rad_passchange"); pairfree(user_reply,"rad_passchange"); reqfree(authreq,"rad_passchange"); return; } /* Get the current password from the database */ curpass = user_check; while(curpass != (VALUE_PAIR *)NULL) { if(curpass->attribute == PW_PASSWORD) { break; } curpass = curpass->next; } if((curpass == (VALUE_PAIR *)NULL) || curpass->strvalue == (char *)NULL) { /* Missing our local copy of the password */ log_err("passchange: from %s - no password found for user %s\n", ipaddr2strp(authreq->ipaddr), namepair->strvalue); send_reject(authreq, (char *)NULL, activefd); pairfree(user_check,"rad_passchange"); pairfree(user_reply,"rad_passchange"); reqfree(authreq,"rad_passchange"); return; } if(strcmp(curpass->strvalue,"UNIX") == 0) { /* Can not change passwords that are not in users file */ log_err("passchange: from %s - system password change not allowed for user %s\n", ipaddr2strp(authreq->ipaddr), namepair->strvalue); send_reject(authreq, (char *)NULL, activefd); pairfree(user_check,"rad_passchange"); pairfree(user_reply,"rad_passchange"); reqfree(authreq,"rad_passchange"); return; } /* Decrypt the old password */ secretlen = strlen(curpass->strvalue); memcpy(string, curpass->strvalue, secretlen); memcpy(string + secretlen, newpasspair->strvalue, AUTH_VECTOR_LEN); md5_calc(pw_digest, string, AUTH_VECTOR_LEN + secretlen); memcpy(passbuf, oldpasspair->strvalue, AUTH_PASS_LEN); for(i = 0;i < AUTH_PASS_LEN;i++) { passbuf[i] ^= pw_digest[i]; } /* Did they supply the correct password ??? */ if(strncmp(passbuf, curpass->strvalue, AUTH_PASS_LEN) != 0) { log_err("passchange: from %s - incorrect password for user %s\n", ipaddr2strp(authreq->ipaddr), namepair->strvalue); send_reject(authreq, (char *)NULL, activefd); pairfree(user_check,"rad_passchange"); pairfree(user_reply,"rad_passchange"); reqfree(authreq,"rad_passchange"); return; } /* Decrypt the new password */ memcpy(string, curpass->strvalue, secretlen); memcpy(string + secretlen, authreq->vector, AUTH_VECTOR_LEN); md5_calc(pw_digest, string, AUTH_VECTOR_LEN + secretlen); memcpy(passbuf, newpasspair->strvalue, AUTH_PASS_LEN); for(i = 0;i < AUTH_PASS_LEN;i++) { passbuf[i] ^= pw_digest[i]; } /* Update the users password */ strncpy(curpass->strvalue, passbuf, AUTH_PASS_LEN); /* Add a new expiration date if we are aging passwords */ if(expiration_seconds != (UINT4)0) { set_expiration(user_check, expiration_seconds); } /* Update the database */ if(user_update(namepair->strvalue, user_check, user_reply) != 0) { send_reject(authreq, (char *)NULL, activefd); log_err("passchange: unable to update password for user %s\n", namepair->strvalue); } else { send_pwack(authreq, activefd); } pairfree(user_check,"rad_passchange"); pairfree(user_reply,"rad_passchange"); reqfree(authreq,"rad_passchange"); return; } #endif /* PASSCHANGE */ /************************************************************************* * * Function: child_authenticate * * Purpose: Process and reply to an authentication request * *************************************************************************/ void child_authenticate(authreq, activefd) AUTH_REQ *authreq; int activefd; { int rad_authenticate(); #ifdef SMARTCARD key_t msg_key; int msg_id; int length; struct sockaddr_in *sin; msg_key = RADIUS_MSG_KEY(getpid()); #endif /* SMARTCARD */ for (;;) { if (rad_authenticate(authreq, activefd) == 0) { break; } #ifdef SMARTCARD if ((msg_id = msgget(msg_key, IPC_CREAT | 0600)) == -1) { log_err("child_authenticate: msgget for key %x for id %d returned error: %s\n", msg_key, msg_id, sys_errlist[errno]); break; } if ((length = msgrcv(msg_id, recv_buffer, sizeof recv_buffer - sizeof(long), 0, 0)) == -1) { log_err("child_authenticate: msgrcv for msgid %d returned error: %s\n", msg_id, sys_errlist[errno]); break; } if (msgctl(msg_id, IPC_RMID, 0) == -1) { log_err("child_authenticate: msgctl for msgid %d returned error: %s\n", msg_id, sys_errlist[errno]); } sin = (struct sockaddr_in *) &rad_saremote; authreq = radrecv( ntohl(sin->sin_addr.s_addr), ntohs(sin->sin_port), authreq->secret, recv_buffer, length); #else /* not SMARTCARD */ break; #endif /* not SMARTCARD */ } } /************************************************************************* * * Function: rad_authenticate * * Purpose: Process and reply to an authentication request * *************************************************************************/ int rad_authenticate(authreq, activefd) AUTH_REQ *authreq; int activefd; { USER_DESC *user_desc; VALUE_PAIR *attr; VALUE_PAIR *auth_item; VALUE_PAIR *callpair; VALUE_PAIR *challenge; VALUE_PAIR *check_item; VALUE_PAIR *get_attribute(); VALUE_PAIR *password_item; VALUE_PAIR *user_check; VALUE_PAIR *user_reply; char auth_name[AUTH_STRING_LEN + 2]; char callfrom[32]; char pw_digest[16]; char string[AUTH_STRING_LEN + 20 + 2]; char umsg[AUTH_STRING_LEN + 2]; char *crypt(); char *encpw; char *ip_hostname(); char *ptr; char *user_msg; char *decrypt_password(); char *pass; int authtype; int chlen; int result; int retval; int speed; int atoi(); int find_client(); int pw_expired(); int unix_group(); int unix_pass(); int vp_check_req(); void calc_digest(); void calc_next_digest(); void pairfree(); void reqfree(); void send_accept(); void send_reject(); #ifdef ACTIVCARD int activcard_auth(); #endif #ifdef SECURID int securid(); #endif /* The username was placed in authreq->name by handle_proxy */ if(strlen(authreq->name) <= (size_t)0) { log_err("auth: access-request from %s ignored; no user name\n", req2strp(authreq)); reqfree(authreq,"rad_authenticate"); return(0); } #ifdef VPORTS if (vports_flag == 1) { switch(vp_check_req(authreq)) { case VP_RET_REJECT: send_reject(authreq, (char *)NULL, activefd); reqfree(authreq,"rad_authenticate"); return(0); break; case VP_RET_ACCEPT: send_accept(authreq, (VALUE_PAIR *)NULL, (char *)NULL, activefd); reqfree(authreq,"rad_authenticate"); return(0); break; case VP_RET_IGNORE: default: break; } } #endif /* VPORTS */ /* calculate the MD5 Password Digest */ calc_digest(pw_digest, authreq, authreq->secret); /* * If the request is processing a menu, service it here. */ if((attr = get_attribute(authreq->request, PW_STATE)) != (VALUE_PAIR *)NULL && strncmp(attr->strvalue, "MENU=", 5) == 0){ process_menu(authreq, activefd, pw_digest); return(0); } callpair = get_attribute(authreq->request, PW_CALLING); if (callpair == (VALUE_PAIR *)NULL || callpair->lvalue > 20) { callfrom[0] = '\0'; } else { sprintf(callfrom," at %s",callpair->strvalue); } /* * Open the user table */ if((user_desc = user_open()) == (USER_DESC *)NULL) { reqfree(authreq,"rad_authenticate"); return(0); } for (;;) { /* Get the user from the database */ if ((result = user_find( authreq->name, auth_name, &user_check, &user_reply, user_desc)) != 0) { log_err("auth: access-request from %s denied for unknown user \"%s\"%s\n", req2strp(authreq), authreq->name, callfrom); send_reject(authreq, (char *)NULL, activefd); reqfree(authreq,"rad_authenticate"); user_close(user_desc); return(0); } /* Validate the user */ /* Look for matching check items */ password_item = (VALUE_PAIR *)NULL; authtype = PW_AUTHTYPE_NONE; user_msg = (char *)NULL; check_item = user_check; while(result == 0 && check_item != (VALUE_PAIR *)NULL) { auth_item = get_attribute(authreq->request, check_item->attribute); switch(check_item->attribute) { case PW_PREFIX: case PW_SUFFIX: break; case PW_EXPIRATION: /* * Check expiration date if we are * doing password aging. */ /* Has this user's password expired */ retval = pw_expired(check_item->lvalue); if(retval < 0) { result = -2; sprintf(umsg,"Password Has Expired\r\n"); user_msg = umsg; } else { if(retval > 0) { sprintf(umsg, "Password Will Expire in %d Days\r\n", retval); user_msg = umsg; } } break; case PW_PASSWORD: if(strcmp(check_item->strvalue, "UNIX") == 0) { authtype = PW_AUTHTYPE_UNIX; } else { authtype = PW_AUTHTYPE_LOCAL; password_item = check_item; } break; case PW_AUTHTYPE: authtype = check_item->lvalue; break; case PW_GROUP: if(!unix_group(auth_name, check_item->strvalue)) { result = -1; } break; case PW_CRYPT_PASSWORD: authtype = PW_AUTHTYPE_CRYPT; password_item = check_item; break; case PW_CONNECT_RATE: auth_item = get_attribute(authreq->request, PW_CONNECT_INFO); if (auth_item != (VALUE_PAIR *)NULL) { speed = atoi(auth_item->strvalue); if (speed > check_item->lvalue) { result = -1; } } break; default: if(auth_item == (VALUE_PAIR *)NULL) { result = -1; break; } switch(check_item->type) { case PW_TYPE_STRING: if(strcmp(check_item->strvalue, auth_item->strvalue) != 0) { result = -1; } break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: if(check_item->lvalue != auth_item->lvalue) { result = -1; } break; default: result = -1; break; } break; } check_item = check_item->next; } if (result != -1) { break; } pairfree(user_check,"rad_authenticate"); pairfree(user_reply,"rad_authenticate"); } user_close(user_desc); /* * At this point we have validated all normal comparisons * for the user. All that is left is the actual authentication. * Authentication will be done based on the authentication type * previously specified. */ if(result == 0) { /* * Decrypt the password in the request. */ pass = decrypt_password(authreq,authreq->secret); if (pass != (char *)NULL) { strncpy(string,pass,AUTH_STRING_LEN); string[AUTH_STRING_LEN] = '\0'; /* always null-term */ } else { string[0] = '\0'; } switch(authtype) { case PW_AUTHTYPE_LOCAL: /* * The local authentication type supports normal * password comparison and the Three-Way CHAP. */ if (password_item == (VALUE_PAIR *)NULL) { log_err("Warning: entry for user \"%s\" is missing Password check item\n",authreq->name); result = -1; } /* * Check to see if we have a CHAP password. */ else if ((auth_item = get_attribute(authreq->request, PW_CHAP_PASSWORD)) != (VALUE_PAIR *)NULL) { /* Use MD5 to verify */ ptr = string; *ptr++ = *auth_item->strvalue; strcpy(ptr, password_item->strvalue); ptr += strlen(password_item->strvalue); if ((challenge = get_attribute(authreq->request, PW_CHAP_CHALLENGE)) != (VALUE_PAIR *)NULL) { chlen = challenge->lvalue; memcpy(ptr, challenge->strvalue, chlen); } else { chlen = AUTH_VECTOR_LEN; memcpy(ptr, authreq->vector, chlen); } md5_calc(pw_digest, string, 1 + chlen + strlen(password_item->strvalue)); /* Compare them */ if(memcmp(pw_digest, auth_item->strvalue + 1, CHAP_VALUE_LENGTH) != 0) { result = -1; } else { result = 0; } } else if (strcmp(password_item->strvalue, string) == 0) { result = 0; } else { result = -1; } break; case PW_AUTHTYPE_UNIX: if(unix_pass(auth_name, string, callfrom) != 0) { result = -1; } break; #ifdef SECURID case PW_AUTHTYPE_SECURID: if(pass != (char *)NULL) { pairfree(user_check,"rad_authenticate"); return( securid(auth_name, string, authreq, user_reply, activefd) ); } else { result = -1; } break; #endif /* SECURID */ case PW_AUTHTYPE_CRYPT: /* password is stored encrypted in string */ if(password_item == (VALUE_PAIR *)NULL) { if(string[0] != '\0') { result = -1; } } else if(pass != (char *)NULL) { encpw = crypt(string,password_item->strvalue); if(strcmp(encpw,password_item->strvalue) != 0) { result = -1; } } else { result = -1; } break; case PW_AUTHTYPE_REJECT: result = -1; break; #ifdef ACTIVCARD case PW_AUTHTYPE_ACTIVCARD: if (pass != (char *)NULL) { pairfree(user_check,"rad_authenticate"); /* activcard calls send_*() as needed */ return ( activcard_auth(auth_name, string, authreq, user_reply, activefd) ); } else { result = -1; } break; #endif /* ACTIVCARD */ case PW_AUTHTYPE_NONE: /* No Password or Auth-Type found in check-items */ DEBUG("entry for user \"%s\" has no Password or Auth-Type check-item\n",authreq->name); result = 0; break; default: log_err("Warning: entry for user \"%s\" has unknown Auth-Type = %d\n",authreq->name, authtype); result = -1; break; } } if(result != 0) { send_reject(authreq, user_msg, activefd); } else { send_accept(authreq, user_reply, user_msg, activefd); } reqfree(authreq,"rad_authenticate"); pairfree(user_check,"rad_authenticate"); pairfree(user_reply,"rad_authenticate"); return(0); } /************************************************************************* * * Function: send_reject * * Purpose: Reply to the request with a REJECT. Also attach * any user message provided. * *************************************************************************/ void send_reject(authreq, msg, activefd) AUTH_REQ *authreq; char *msg; int activefd; { u_char code; int total_length; int build_packet(); void send_packet(); #ifdef PASSCHANGE if(authreq->code == PW_PASSWORD_REQUEST) { code = PW_PASSWORD_REJECT; } else { #endif PASSCHANGE code = PW_AUTHENTICATION_REJECT; report[RR_REJECT]++; #ifdef PASSCHANGE } #endif PASSCHANGE DEBUG("sending reject to %s\n", req2strp(authreq)); total_length = build_packet(authreq,(VALUE_PAIR *)NULL,msg,code,FW_REPLY,send_buffer); /* Send it to the user */ send_packet(activefd, authreq->ipaddr, authreq->udp_port, send_buffer, total_length); } /************************************************************************* * * Function: send_challenge * * Purpose: Reply to the request with a CHALLENGE. Also attach * any user message provided and a state value. * *************************************************************************/ void send_challenge(authreq, msg, state, activefd) AUTH_REQ *authreq; char *msg; char *state; int activefd; { VALUE_PAIR *pairalloc(); VALUE_PAIR *reply; int len; int total_length; int build_packet(); void send_packet(); report[RR_CHALLENGE]++; if((state != (char *)NULL) && ((len=strlen(state)) > (size_t)0)) { reply = pairalloc("send_challenge"); memcpy(reply->name,"State",5); reply->attribute = PW_STATE; reply->type = PW_TYPE_STRING; if (len > AUTH_STRING_LEN) { len = AUTH_STRING_LEN; } reply->lvalue = len; memcpy(reply->strvalue,state,len); } else { reply = (VALUE_PAIR *)NULL; } DEBUG("sending challenge to %s\n", req2strp(authreq)); total_length = build_packet(authreq,reply,msg,PW_ACCESS_CHALLENGE,FW_REPLY,send_buffer); send_packet(activefd,authreq->ipaddr,authreq->udp_port,send_buffer,total_length); } #ifdef PASSCHANGE /************************************************************************* * * Function: send_pwack * * Purpose: Reply to the request with an ACKNOWLEDGE. * User password has been successfully changed. * *************************************************************************/ void send_pwack(authreq, activefd) AUTH_REQ *authreq; int activefd; { AUTH_HDR *auth; struct sockaddr_in saremote; struct sockaddr_in *sin; char *ip_hostname(); char digest[AUTH_VECTOR_LEN]; int secretlen; auth = (AUTH_HDR *)send_buffer; /* Build standard response header */ auth->code = PW_PASSWORD_ACK; auth->id = authreq->id; memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN); auth->length = htons(AUTH_HDR_LEN); /* Calculate the response digest */ secretlen = strlen((const char *)authreq->secret); memcpy(send_buffer + AUTH_HDR_LEN, authreq->secret, secretlen); md5_calc(digest, (char *)auth, AUTH_HDR_LEN + secretlen); memcpy(auth->vector, digest, AUTH_VECTOR_LEN); memset(send_buffer + AUTH_HDR_LEN, 0, secretlen); sin = (struct sockaddr_in *) &saremote; memset ((char *) sin, '\0', sizeof (saremote)); sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(authreq->ipaddr); sin->sin_port = htons(authreq->udp_port); DEBUG("Sending PW Ack of id %d to %s\n", authreq->id, ipaddr2strp(authreq->ipaddr)); /* Send it to the user */ sendto(activefd, (char *)auth, (int)AUTH_HDR_LEN, (int)0, (struct sockaddr *)&saremote, sizeof(struct sockaddr_in)); } #endif /* PASSCHANGE */ /************************************************************************* * * Function: send_accept * * Purpose: Reply to the request with an ACKNOWLEDGE. Also attach * reply attribute value pairs and any user message provided. * *************************************************************************/ void send_accept(authreq, reply, msg, activefd) AUTH_REQ *authreq; VALUE_PAIR *reply; char *msg; int activefd; { VALUE_PAIR *menu_attr; VALUE_PAIR *get_attribute(); char *get_menu(); char state_value[120]; int total_length; int build_packet(); void send_packet(); /* Check to see if the response is a menu */ if((menu_attr = get_attribute(reply, PW_MENU)) != (VALUE_PAIR *)NULL) { msg = get_menu(menu_attr->strvalue); sprintf(state_value, "MENU=%s", menu_attr->strvalue); send_challenge(authreq, msg, state_value, activefd); return; } report[RR_ACCEPT]++; DEBUG("sending accept to %s\n", req2strp(authreq)); total_length = build_packet(authreq,reply,msg,PW_AUTHENTICATION_ACK,FW_REPLY,send_buffer); /* Send it to the user */ send_packet(activefd, authreq->ipaddr, authreq->udp_port, send_buffer, total_length); } /************************************************************************* * * Function: build_packet * * Purpose: called by routines to build RADIUS packet * * forward = 0 FW_REPLY replying to client * 1 FW_SERVER forwarding request to remote server * 2 FW_CLIENT forwarding response to client * *************************************************************************/ int build_packet(authreq,reply,msg,code,forward,buffer) AUTH_REQ *authreq; VALUE_PAIR *reply; char *msg; u_char code; int forward; u_char *buffer; { AUTH_HDR *auth; VALUE_PAIR *item; u_short total_length; u_char *ptr; u_char *lptr; int len; UINT4 lvalue; UINT4 vendor; u_char digest[16]; int secretlen; VALUE_PAIR *get_attribute(); int block_len; char *ipaddr2strp(); auth = (AUTH_HDR *)buffer; /* Build standard header */ auth->code = code; auth->id = authreq->id; total_length = AUTH_HDR_LEN; /* Load up the configuration values for the user */ ptr = auth->data; while(reply != (VALUE_PAIR *)NULL) { debug_pair(reply); *ptr++ = reply->attribute; lptr = ptr; if (reply->attribute == PW_VENDOR && reply->vendor != 0) { ptr++; total_length += 6; vendor = htonl(reply->vendor); memcpy(ptr,&vendor,sizeof(UINT4)); ptr += 4; *ptr++ = reply->vsattribute; if (reply->type == PW_TYPE_STRING) { *lptr = reply->lvalue + 8; } else { *lptr = 12; } } switch(reply->type) { case PW_TYPE_STRING: len = reply->lvalue; if (len > AUTH_STRING_LEN) { len = AUTH_STRING_LEN; } *ptr++ = len + 2; memcpy(ptr, reply->strvalue,len); ptr += len; total_length += len + 2; break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: *ptr++ = sizeof(UINT4) + 2; lvalue = htonl(reply->lvalue); memcpy(ptr, &lvalue, sizeof(UINT4)); ptr += sizeof(UINT4); total_length += sizeof(UINT4) + 2; break; default: break; } reply = reply->next; } /* Append the user message */ if(msg != (char *)NULL && (len = strlen(msg)) > 0) { while(len > 0) { if(len > AUTH_STRING_LEN) { block_len = AUTH_STRING_LEN; } else { block_len = len; } *ptr++ = PW_PORT_MESSAGE; *ptr++ = block_len + 2; memcpy(ptr, msg, block_len); msg += block_len; ptr += block_len; total_length += block_len + 2; len -= block_len; } } /* Copy over any proxy-states, in order */ if (forward == FW_REPLY) { item = authreq->request; while (item != (VALUE_PAIR *)NULL) { if (item->attribute == PW_PROXY) { debug_pair(item); *ptr++ = PW_PROXY; len = item->lvalue; *ptr++ = len + 2; memcpy(ptr,item->strvalue,len); ptr += len; total_length += len + 2; } item = item->next; } } auth->length = htons(total_length); if (code == PW_AUTHENTICATION_ACK || code == PW_AUTHENTICATION_REJECT || code == PW_ACCESS_CHALLENGE || code == PW_ACCOUNTING_RESPONSE) { /* The Authenticator field in an Response packet is called the Response Authenticator, and contains a one-way MD5 hash calculated over a stream of octets consisting of the Response Code, Identifier, Length, the Request Authenticator field from the Request packet being replied to, and the response attributes if any, followed by the shared secret. The resulting 16 octet MD5 hash value is stored in the Authenticator field of the Response packet. */ /* Append secret and calculate the response digest */ memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN); secretlen = strlen((const char *)authreq->secret); memcpy(buffer + total_length, authreq->secret, secretlen); md5_calc(digest, (char *)auth, total_length + secretlen); memcpy(auth->vector, digest, AUTH_VECTOR_LEN); memset(buffer + total_length, 0, secretlen); } else if (code == PW_ACCOUNTING_REQUEST) { /* Forwarding */ memset(auth->vector, 0, AUTH_VECTOR_LEN); secretlen = strlen(authreq->forw_secret); memcpy(buffer + total_length, authreq->forw_secret, secretlen); md5_calc(digest, buffer, total_length + secretlen); memcpy(auth->vector,digest,AUTH_VECTOR_LEN); memset(buffer + total_length, 0, secretlen); } else if (code == PW_AUTHENTICATION_REQUEST) { /* Forwarding */ memcpy(auth->vector, authreq->vector, AUTH_VECTOR_LEN); } return ((int)total_length); } /************************************************************************* * * Function: decrypt_password * * Purpose: decrypts the User-Password attribute in place in * authreq->request using authreq->vector and * secret and the algorithm specified in the * RADIUS RFC, and returns a pointer to the Password * if successful, otherwise NULL * *************************************************************************/ char * decrypt_password(authreq,secret) AUTH_REQ *authreq; char *secret; { VALUE_PAIR *auth_item; VALUE_PAIR *get_attribute(); int i; int j; int passlen; char hold_vector[AUTH_VECTOR_LEN]; char pw_digest[16]; char *string; char *ptr; void calc_digest(); void calc_next_digest(); calc_digest(pw_digest, authreq, secret); /* * Decrypt the password in the request. */ if((auth_item = get_attribute(authreq->request, PW_PASSWORD)) == (VALUE_PAIR *)NULL) { return (char *)NULL; } passlen = auth_item->lvalue; if(passlen > AUTH_MAXPASS_LEN) { log_err("decrypt_password: Password length %d > %d max not allowed\n",passlen, AUTH_MAXPASS_LEN); passlen = AUTH_MAXPASS_LEN; } string = auth_item->strvalue; ptr = string; for(i = 0;i < passlen;i += AUTH_PASS_LEN) { /* * Store the vector to be used in next segment * of the encrypted password. */ memcpy(hold_vector, ptr, AUTH_VECTOR_LEN); /* Decrypt from the digest */ for(j = 0;j < AUTH_PASS_LEN;j++) { *ptr ^= pw_digest[j]; ptr++; } /* Calculate the next digest if necessary */ if(i + AUTH_PASS_LEN < passlen) { calc_next_digest(pw_digest, secret, hold_vector); } } *ptr = '\0'; /* this depends on the fact that auth_item->strvalue always has an extra byte available */ return string; } /************************************************************************* * * Function: encrypt_password * * Purpose: encrypts the User-Password attribute in place in * authreq->request using authreq->vector and * secret and the algorithm specified in the * RADIUS RFC, and returns a pointer to the Password * if successful, otherwise NULL * *************************************************************************/ char * encrypt_password(authreq,secret) AUTH_REQ *authreq; char *secret; { VALUE_PAIR *auth_item; VALUE_PAIR *get_attribute(); int i; int j; int passlen; char *hold_vector; char pw_digest[16]; char *string; char *ptr; void calc_digest(); void calc_next_digest(); calc_digest(pw_digest, authreq, secret); /* * Decrypt the password in the request. */ if((auth_item = get_attribute(authreq->request, PW_PASSWORD)) == (VALUE_PAIR *)NULL) { return (char *)NULL; } passlen = auth_item->lvalue; if(passlen > AUTH_MAXPASS_LEN) { log_err("encrypt_password: Password length %d > %d not allowed, truncating\n",passlen, AUTH_MAXPASS_LEN); passlen = AUTH_MAXPASS_LEN; auth_item->lvalue = AUTH_MAXPASS_LEN; auth_item->strvalue[AUTH_MAXPASS_LEN] = '\0'; } string = auth_item->strvalue; ptr = string; for(i = 0;i < passlen;i += AUTH_PASS_LEN) { /* Encrypt using the digest */ hold_vector = ptr; for(j = 0;j < AUTH_PASS_LEN;j++) { *ptr ^= pw_digest[j]; ptr++; } /* Calculate the next digest if necessary */ if(i < passlen) { calc_next_digest(pw_digest, secret, hold_vector); } } *ptr = '\0'; /* this depends on the fact that auth_item->strvalue always has an extra byte available */ return string; } /************************************************************************* * * Function: calc_digest * * Purpose: Validates the requesting client NAS. Calculates the * digest to be used for decrypting the users password * based on the clients private key. * *************************************************************************/ void calc_digest(digest, authreq, secret) u_char *digest; AUTH_REQ *authreq; u_char *secret; { u_char buffer[128]; int secretlen; /* Use the secret to setup the decryption digest */ memset(buffer, 0, sizeof(buffer)); secretlen = strlen((char *)secret); memcpy((char *)buffer, (char *)secret,secretlen); memcpy(buffer + secretlen, authreq->vector, AUTH_VECTOR_LEN); md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN); memset(buffer, 0, secretlen+AUTH_VECTOR_LEN); return; } /************************************************************************* * * Function: calc_next_digest * * Purpose: Calculates the digest to be used for decrypting the * users password past the first 16 octets based on the clients * private key. * *************************************************************************/ void calc_next_digest(digest, secret, vector) u_char *digest; u_char *secret; u_char *vector; { u_char buffer[128]; int secretlen; /* Use the secret to setup the decryption digest */ memset(buffer, 0, sizeof(buffer)); secretlen = strlen((const char *)secret); strcpy((char *)buffer, (const char *)secret); memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN); md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN); memset(buffer, 0, sizeof(buffer)); } /************************************************************************* * * Function: client_hostname * * Purpose: Return the cached client name if we have one. Otherwise * use the regular ip_hostname() function. * *************************************************************************/ char * client_hostname(ipaddr) UINT4 ipaddr; { u_char secret[64]; char hostnm[MAX_HOST_SIZE]; char *ip_hostname(); int find_client(); /* Look at the last used entry first */ if(ipaddr == cached_ipaddr) { return(cached_hostnm); } if(find_client(ipaddr, secret, hostnm) != 0) { memset(secret, 0, sizeof(secret)); return(cached_hostnm); /* set by find_client() */ } return(ip_hostname(ipaddr)); } /************************************************************************* * * Function: find_client * * Purpose: Retrieve the client name and secret from the temporary * DBM client database. * *************************************************************************/ int find_client(ipaddr, secret, hostnm) UINT4 ipaddr; char *secret; char *hostnm; { DBM *db; char buffer[MAX_LINE_SIZE]; char ip_str[32]; datum contentd; datum named; int ret; void ipaddr2str(); /* Find the client in the database */ sprintf((char *)buffer, "%s/%s", radius_dir, RADIUS_CLIENT_CACHE); # ifdef NDBM if((db = dbm_open(buffer, O_RDONLY, 0600)) == (DBM *)NULL) { # else /* not NDBM */ if(dbminit(buffer) != 0) { # endif /* NDBM */ log_err("could not read %s to find clients\n", buffer); return(-1); } ipaddr2str(ip_str, ipaddr); named.dptr = ip_str; named.dsize = strlen(ip_str); contentd = dbm_fetch(db, named); if(contentd.dsize == 0 || contentd.dptr == NULL) { dbm_close(db); return(-1); } if (contentd.dsize >= MAX_LINE_SIZE) { dbm_close(db); log_err("client %s length %d > %d in client cache\n", ip_str, contentd.dsize, MAX_LINE_SIZE-1); return(-1); } /* convoluted method of working around Solaris x86 2.5 bug */ memcpy(buffer,contentd.dptr,contentd.dsize-1); buffer[contentd.dsize - 1] = '\n'; buffer[contentd.dsize] = '\0'; if((ret=sscanf((const char *)buffer, "%s%s", hostnm, secret)) != 2) { dbm_close(db); log_err("client cache entry for %s could not be parsed (%d)\n", ip_str,ret); return(-1); } /* Build a cached hostname entry for client_hostname() to use */ strncpy(cached_hostnm, hostnm, MAX_HOST_SIZE); cached_hostnm[MAX_HOST_SIZE-1] = '\0'; cached_ipaddr = ipaddr; dbm_close(db); return(0); } /************************************************************************* * * Function: update_clients * * Purpose: Check last modified time on clients file and build a * new temporary DBM client database if the file has been * changed. * *************************************************************************/ int update_clients() { static time_t last_update_time; struct stat statbuf; struct stat statbuf2; datum named; datum contentd; DBM *db; FILE *clientfd; u_char buffer[256]; u_char oldcache[256]; u_char newcache[256]; u_char secret[64]; char hostnm[128]; char ip_str[64]; int nclients; int rcode; int rename(); int s1; int s2; UINT4 ipaddr; UINT4 get_ipaddr(); int fclose(); void ipaddr2str(); nclients = 0; rcode = 0; /* Check last modified time of clients file */ sprintf((char *)buffer, "%s/%s", radius_dir, RADIUS_CLIENTS); if(stat(buffer, &statbuf) != 0) { log_err("Error: clients file %s not found\n", buffer); return(-1); } if(statbuf.st_mtime == last_update_time) { /* nothing to update */ return(0); } cached_ipaddr = 0; /* Open the standard clients file */ if((clientfd = fopen((const char *)buffer, "r")) == (FILE *)NULL) { log_err("Error: could not read clients file %s\n", buffer); return(-1); } /* Open and truncate the clients DBM cache file */ sprintf((char *)oldcache, "%s/%s", radius_dir, RADIUS_CLIENT_CACHE); sprintf((char *)newcache, "%s.lock", oldcache); #if defined(NDBM) if((db = dbm_open(newcache, O_RDWR | O_CREAT | O_TRUNC, 0600)) == (DBM *)NULL) { #else if(dbminit(newcache) != 0) { #endif log_err("Error: could not create temporary client cache file %s\n",newcache); return(-1); } while(fgets((char *)buffer, sizeof(buffer), clientfd) != (char *)NULL) { if(*buffer == '#') { continue; } if(sscanf((const char *)buffer, "%s%s", hostnm, secret) != 2) { continue; } if((ipaddr = get_ipaddr(hostnm)) != (UINT4)0) { ipaddr2str(ip_str, ipaddr); named.dptr = ip_str; named.dsize = strlen(ip_str); contentd.dptr = (char *)buffer; contentd.dsize = strlen(buffer); #if defined(NDBM) if(dbm_store(db, named, contentd, DBM_INSERT) != 0) { #else /* not NDBM */ if(store(named, contentd) != 0) { #endif /* NDBM */ log_err("could not cache client datum for host %s\n", hostnm); rcode = -1; } else { nclients++; } } } dbm_close(db); fclose(clientfd); s1 = strlen(newcache); strcat(newcache,".db"); if (stat(newcache,&statbuf2) == 0) { strcat(oldcache,".db"); if (rename(newcache,oldcache) != 0) { log_err("Error: could not move client cache file %s to %s, error %d\n",newcache,oldcache,errno); return(-1); } else { DEBUG("updated client cache with %d clients\n",nclients); } } else { newcache[s1] = '\0'; s2 = strlen(oldcache); strcat(newcache,".pag"); strcat(oldcache,".pag"); if (rename(newcache,oldcache) != 0) { log_err("Error: could not move client cache file %s to %s, error %d\n",newcache,oldcache,errno); return(-1); } newcache[s1] = '\0'; oldcache[s2] = '\0'; strcat(newcache,".dir"); strcat(oldcache,".dir"); if (rename(newcache,oldcache) != 0) { log_err("Error: could not move client cache file %s to %s, error %d\n",newcache,oldcache,errno); rcode = -1; } else { DEBUG("updated client cache with %d clients\n",nclients); } } if (rcode == 0) { last_update_time = statbuf.st_mtime; } return(rcode); } /************************************************************************* * * Function: debug_pair * * Purpose: Print the Attribute-value pair to the desired File. * *************************************************************************/ void debug_pair(pair) VALUE_PAIR * pair; { void fprint_attr_val(); if(debug_flag) { fprint_attr_val(-1, pair); } } /************************************************************************* * * Function: usage * * Purpose: Display the syntax for starting this program. * *************************************************************************/ void usage() { fprintf(stderr, "Usage: %s", progname); fprintf(stderr, " [-a ]"); fprintf(stderr, " [-b]"); fprintf(stderr, " [-d ]"); fprintf(stderr, " [-h]"); fprintf(stderr, " [-f ]"); fprintf(stderr, " [-i ]"); fprintf(stderr, " [-l ]"); fprintf(stderr, " [-o]"); fprintf(stderr, " [-p ]"); fprintf(stderr, " [-q ]"); fprintf(stderr, " [-s]"); fprintf(stderr, " [-t ]"); fprintf(stderr, " [-v]"); fprintf(stderr, " [-w ]"); fprintf(stderr, " [-x]\n"); exit(-1); } /************************************************************************* * * Function: config_init * * Purpose: intializes configuration values * * expiration_seconds - When updating a user password, * the amount of time to add to the current time * to set the time when the password will expire. * This is stored as the VALUE Password-Expiration * in the dictionary as number of days. * * warning_seconds - When acknowledging a user authentication * time remaining for valid password to notify user * of password expiration. * *************************************************************************/ int config_init() { DICT_VALUE *dval; DICT_VALUE *dict_valfind(); if((dval = dict_valfind("Password-Expiration")) == (DICT_VALUE *)NULL) { expiration_seconds = (UINT4)0; } else { expiration_seconds = dval->value * (UINT4)SECONDS_PER_DAY; } if((dval = dict_valfind("Password-Warning")) == (DICT_VALUE *)NULL) { warning_seconds = (UINT4)0; } else { warning_seconds = dval->value * (UINT4)SECONDS_PER_DAY; } strcpy(unknown,"unknown"); /* for client caching error return */ return(0); } /************************************************************************* * * Function: set_expiration * * Purpose: Set the new expiration time by updating or adding the Expiration attribute-value pair. * *************************************************************************/ int set_expiration(user_check, expiration) VALUE_PAIR *user_check; UINT4 expiration; { VALUE_PAIR *exppair; VALUE_PAIR *prev; VALUE_PAIR *pairalloc(); int gettimeofday(); struct timeval tp; struct timezone tzp; if(user_check == (VALUE_PAIR *)NULL) { return(-1); } /* Look for an existing expiration entry */ exppair = user_check; prev = (VALUE_PAIR *)NULL; while(exppair != (VALUE_PAIR *)NULL) { if(exppair->attribute == PW_EXPIRATION) { break; } prev = exppair; exppair = exppair->next; } if(exppair == (VALUE_PAIR *)NULL) { /* Add a new attr-value pair */ exppair = pairalloc("set_expiration"); /* Initialize it */ strcpy(exppair->name, "Expiration"); exppair->attribute = PW_EXPIRATION; exppair->type = PW_TYPE_DATE; /* Attach it to the list. */ prev->next = exppair; } /* calculate a new expiration */ gettimeofday(&tp, &tzp); exppair->lvalue = tp.tv_sec + expiration; return(0); } /************************************************************************* * * Function: pw_expired * * Purpose: Tests to see if the users password has expired. * * Return: Number of days before expiration if a warning is required * otherwise 0 for success and -1 for failure. * *************************************************************************/ int pw_expired(exptime) UINT4 exptime; { struct timeval tp; struct timezone tzp; UINT4 exp_remain; int exp_remain_int; int gettimeofday(); if(expiration_seconds == (UINT4)0) { /* expiration not enabled */ return(0); } gettimeofday(&tp, &tzp); if(tp.tv_sec > exptime) { return(-1); } if(warning_seconds != (UINT4)0) { if(tp.tv_sec > exptime - warning_seconds) { exp_remain = exptime - tp.tv_sec; exp_remain /= (UINT4)SECONDS_PER_DAY; exp_remain_int = exp_remain; return(exp_remain_int); } } return(0); } /************************************************************************* * * Function: get_attribute * * Purpose: Retrieve a specific value-pair from a list of value-pairs. * *************************************************************************/ VALUE_PAIR * get_attribute(value_list, attribute) VALUE_PAIR *value_list; int attribute; { while(value_list != (VALUE_PAIR *)NULL) { if(value_list->attribute == attribute) { return(value_list); } value_list = value_list->next; } return((VALUE_PAIR *)NULL); } void sig_fatal(sig) int sig; { #ifdef ACTIVCARD void activcard_exit(); #endif void rad_exit(); if(acct_pid > 0) { kill(acct_pid, SIGKILL); } #ifdef ACTIVCARD activcard_exit(); /* close activcard session */ #endif log_err("exit on signal %d\n", sig); rad_exit(1); } void sig_hup(sig) int sig; { return; } void sig_usr1(sig) int sig; { extern int debug_flag; void log_counters(); debug_flag++; log_err("debug mode %d\n",debug_flag); log_counters(); return; } void sig_usr2(sig) int sig; { extern int debug_flag; void log_counters(); if (debug_flag) { log_err("debug mode 0\n"); } debug_flag = 0; log_counters(); return; } void rad_exit(rc) int rc; { void log_counters(); #ifdef SECURID AUTH_REQ *curreq; key_t msg_key; int msg_id; if (rad_spawned_child_pid == 0) { /* * child clean up */ msg_key = RADIUS_MSG_KEY(getpid()); if ((msg_id = msgget(msg_key, 0600)) != -1) { msgctl(msg_id, IPC_RMID, 0); } } else { /* * parent clean up */ curreq = first_request; while(curreq != (AUTH_REQ *)NULL) { msg_key = RADIUS_MSG_KEY(curreq->child_pid); if ((msg_id = msgget(msg_key, 0600)) != -1) { msgctl(msg_id, IPC_RMID, 0); } curreq = curreq->next; } } #endif /* SECURID */ log_counters(); exit(rc); } void log_counters() { extern int report[]; void memreport(); void proxy_report(); log_err("counters %d %d / %d %d / accept %d reject %d challenge %d response %d\n", report[RR_PORT1],report[RR_PORT2],report[RR_PORT3],report[RR_PORT4], report[RR_ACCEPT],report[RR_REJECT],report[RR_CHALLENGE], report[RR_ACCOUNT]); memreport(); proxy_report(); } radiusd-livingston-2.1/src/radpass.c0100644000175000017500000001775006734270173015427 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: radpass.c,v 1.9 1999/06/23 23:40:43 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include "radius.h" #define MAXPWNAM 8 #define MAXPASS 16 u_char recv_buffer[4096]; u_char send_buffer[4096]; u_char *progname; int sockfd; u_char vector[AUTH_VECTOR_LEN]; u_char oldpass[AUTH_PASS_LEN]; main(argc, argv) int argc; u_char *argv[]; { int salen; int result; struct sockaddr salocal; struct sockaddr saremote; struct sockaddr_in *sin; struct servent *svp; u_short svc_port; AUTH_HDR *auth; u_char *username; u_char newpass1[AUTH_PASS_LEN]; u_char newpass2[AUTH_PASS_LEN]; u_char passbuf[AUTH_PASS_LEN]; u_char md5buf[256]; u_char *oldvector; UINT4 get_ipaddr(); UINT4 auth_ipaddr; u_short local_port; int total_length; u_char *ptr; int length; int secretlen; int i; char *getpass(); progname = argv[0]; if(argc != 2) { usage(); } /* Get the user name */ username = argv[1]; svp = getservbyname ("radius", "udp"); if (svp == (struct servent *) 0) { fprintf (stderr, "No such service: %s/%s\n", "radius", "udp"); exit(-1); } svc_port = ntohs((u_short) svp->s_port); /* Get the IP address of the authentication server */ if((auth_ipaddr = get_ipaddr("radius-server")) == (UINT4)0) { fprintf(stderr, "Couldn't find host radius-server\n"); exit(-1); } sockfd = socket (AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { (void) perror ("socket"); exit(-1); } sin = (struct sockaddr_in *) & salocal; memset ((char *) sin, '\0', sizeof (salocal)); sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; local_port = 1025; do { local_port++; sin->sin_port = htons((u_short)local_port); } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) && local_port < 64000); if(local_port >= 64000) { close(sockfd); (void) perror ("bind"); exit(-1); } printf("Changing Password for user %s\n", username); /* Get their old password */ strcpy((char *)oldpass, getpass("Old Password:")); if(*oldpass == '\0') { exit(0); } /* Get their new password */ strcpy((char *)newpass1, getpass("New Password:")); if(*newpass1 == '\0') { exit(0); } /* Get their new password again */ strcpy((char *)newpass2, getpass("Re-type New Password:")); if(strcmp(newpass1, newpass2) != 0) { printf("New Passwords didn't match\n"); exit(-1); } /* Build a password change request */ auth = (AUTH_HDR *)send_buffer; auth->code = PW_PASSWORD_REQUEST; auth->id = 0; random_vector(vector); memcpy(auth->vector, vector, AUTH_VECTOR_LEN); total_length = AUTH_HDR_LEN; ptr = auth->data; /* User Name */ *ptr++ = PW_USER_NAME; length = strlen(username); if(length > MAXPWNAM) { length = MAXPWNAM; } *ptr++ = length + 2; memcpy(ptr, username, length); ptr += length; total_length += length + 2; /* New Password */ *ptr++ = PW_PASSWORD; *ptr++ = AUTH_PASS_LEN + 2; /* Encrypt the Password */ length = strlen(newpass1); if(length > MAXPASS) { length = MAXPASS; } memset(passbuf, 0, AUTH_PASS_LEN); memcpy(passbuf, newpass1, length); /* Calculate the MD5 Digest */ secretlen = strlen(oldpass); strcpy(md5buf, oldpass); memcpy(md5buf + secretlen, auth->vector, AUTH_VECTOR_LEN); md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN); oldvector = ptr; /* Xor the password into the MD5 digest */ for(i = 0;i < AUTH_PASS_LEN;i++) { *ptr++ ^= passbuf[i]; } total_length += AUTH_PASS_LEN + 2; /* Old Password */ *ptr++ = PW_OLD_PASSWORD; *ptr++ = AUTH_PASS_LEN + 2; /* Encrypt the Password */ length = strlen(oldpass); if(length > MAXPASS) { length = MAXPASS; } memset(passbuf, 0, AUTH_PASS_LEN); memcpy(passbuf, oldpass, length); /* Calculate the MD5 Digest */ secretlen = strlen(oldpass); strcpy(md5buf, oldpass); memcpy(md5buf + secretlen, oldvector, AUTH_VECTOR_LEN); md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN); /* Xor the password into the MD5 digest */ for(i = 0;i < AUTH_PASS_LEN;i++) { *ptr++ ^= passbuf[i]; } total_length += AUTH_PASS_LEN + 2; auth->length = htonl(total_length); sin = (struct sockaddr_in *) & saremote; memset ((char *) sin, '\0', sizeof (saremote)); sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(auth_ipaddr); sin->sin_port = htons(svc_port); sendto(sockfd, (char *)auth, (int)total_length, (int)0, &saremote, sizeof(struct sockaddr_in)); salen = sizeof (saremote); result = recvfrom (sockfd, (char *) recv_buffer, (int) sizeof(recv_buffer), (int) 0, & saremote, & salen); if(result > 0) { result_recv(sin->sin_addr.s_addr, sin->sin_port, recv_buffer, result); exit(0); } (void) perror ("recv"); close(sockfd); exit(0); } result_recv(host, udp_port, buffer, length) UINT4 host; u_short udp_port; u_char *buffer; int length; { AUTH_HDR *auth; int totallen; char *ip_hostname(); u_char reply_digest[AUTH_VECTOR_LEN]; u_char calc_digest[AUTH_VECTOR_LEN]; int secretlen; auth = (AUTH_HDR *)buffer; totallen = ntohs(auth->length); if(totallen != AUTH_HDR_LEN) { printf("Received invalid reply length from server\n"); exit(-1); } /* Verify the reply digest */ memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN); memcpy(auth->vector, vector, AUTH_VECTOR_LEN); secretlen = strlen(oldpass); memcpy(buffer + AUTH_HDR_LEN, oldpass, secretlen); md5_calc(calc_digest, (char *)auth, AUTH_HDR_LEN); if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) { printf("Warning: Received invalid reply digest from server\n"); } if(auth->code == PW_PASSWORD_ACK) { printf("Password successfully changed\n"); } else { printf("Request Denied\n"); } } usage() { printf("Usage: %s username\n", progname); exit(-1); } random_vector(vector) u_char *vector; { int randno; int i; srand(time(0)); for(i = 0;i < AUTH_VECTOR_LEN;) { randno = rand(); memcpy(vector, &randno, sizeof(int)); vector += sizeof(int); i += sizeof(int); } } radiusd-livingston-2.1/src/radtest.c0100644000175000017500000004006406734270173015432 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /*********************************************************************** RADIUS client test program RADIUS 2.1 includes an example client program called radtest, that sends a RADIUS packet to a server running on the same host as radtest, and prints out the attributes returned. It doesn't support accounting packets yet. It always fills in the NAS-IP-Address as 127.0.0.1 and the NAS-Port as 1. Passwords longer than 16 characters are not supported. It looks for its dictionary in the same directory its run from. radtest -v prints the version. radtest -h prints help: ./radtest -d called_id -f -g calling_id -h -i id -p port -s secret -t type -v -x -u username password The other flags work as follows: -a (not implemented yet) -d Called Station Id -f Send framed dialin hint -g Calling Station Id -i Use id as the packet identifier -n (not implemented yet) -p Use port as the port (defaults to definition in /etc/services, or 1645) -r (not implemented yet) -s to specify shared secret (defaults to "localkey") -t send type as service type (overrides -f) -u Specifies username and password (notice that this takes two arguments) -x sets debugging level (not used for anything yet) ************************************************************************/ static char sccsid[] = "$Id: radtest.c,v 1.1 1999/06/23 23:40:43 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include "stdio.h" #include "stdlib.h" #include "errno.h" #include "sys/types.h" #include "sys/socket.h" #include "sys/param.h" #include "sys/time.h" #include "netdb.h" #include "netinet/in.h" #include "radius.h" int fd; char * host_name; struct sockaddr_in addr; struct hostent * hostent; char * secret; int secret_len; char * progname; u_char req_id; char r_buf[4096]; char s_buf[4096]; char u_name[256]; char u_passwd[256]; int u_name_len; int u_passwd_len; int debug_flag = 0; int debug_mem = 0; char *radius_dir = "."; char *radius_log = "/dev/tty"; UINT4 now = 0; main(argc, argv) char * argv[]; { AUTH_HDR *ah; AUTH_REQ *authreq; AUTH_REQ *radrecv(); VALUE_PAIR *pair; char *called_id; char *calling_id; char argnum; char argval; fd_set fdset; int acct_flag; int count; int frame_flag; int host; int i; int len; int rc; int sa_len; int service_type; int val; int verbose_flag; struct sockaddr_in sa_ihd; struct timeval tv; struct servent * svp; u_char *cp; u_char alen; u_char id; u_short radius_port; void rad_exit(); void usage(); void version(); u_short lport; char passwd[AUTH_PASS_LEN]; char md5_buf[1024]; acct_flag = 0; count = 1; frame_flag = 0; id = 0; service_type = 0; /* default is not to send service type */ verbose_flag = 0; secret = "localkey"; host_name = "localhost"; radius_port = 0; radius_dir = "."; /* always looks in current dir for dictionary */ called_id = NULL; calling_id = NULL; progname = *argv++; argc--; while(argc > 0) { if(**argv != '-') { usage(); } argval = *(*argv + 1); argnum = *(*argv + 2); argc--; argv++; switch(argval) { case 'a': /* accounting packet */ acct_flag = 1; break; case 'd': /* calleD station id */ if(argc == 0) { usage(); } called_id = *argv; argc--; argv++; break; case 'f': frame_flag = 1; break; case 'g': /* callinG station id */ if(argc == 0) { usage(); } calling_id = *argv; argc--; argv++; break; case 'h': usage(); break; case 'i': /* id to use */ if(argc == 0) { usage(); } id = (u_char)(strtol(*argv, 0, 10) & 0x000000ff); argc--; argv++; break; case 'n': /* count not implemented yet */ usage(); if(argc == 0) { usage(); } count = (u_short)strtol(*argv, 0, 10); argc--; argv++; break; case 'p': /* set radius port */ if(argc == 0) { usage(); } radius_port = (u_short)atoi(*argv); argc--; argv++; break; case 'r': /* RADIUS server to send to */ if(argc == 0) { usage(); } host_name = *argv; argc--; argv++; break; case 's': /* shared secret */ if(argc == 0) { usage(); } secret = *argv; argc--; argv++; break; case 't': /* set service type */ if(argc == 0) { usage(); } service_type = (u_short)atoi(*argv); argc--; argv++; break; case 'u': /* username and password */ if(argc < 2) { usage(); } strcpy(u_name,*argv); argv++; strcpy(u_passwd,*argv); argv++; argc -= 2; break; case 'v': version(); break; case 'x': if (isdigit(argnum)) { verbose_flag = argnum - '0'; } else { verbose_flag++; } break; default: usage(); break; } } /* Initialize the dictionary */ if(dict_init() != 0) { rad_exit(-1); } secret_len = strlen(secret); if (radius_port) { lport = htons(radius_port); } else { if (acct_flag) { svp = getservbyname ("radacct", "udp"); if (svp != (struct servent *) 0) { lport = (u_short) svp->s_port; } else { lport = htons(ntohs(PW_AUTH_UDP_PORT)); } } else { svp = getservbyname ("radius", "udp"); if (svp != (struct servent *) 0) { lport = (u_short) svp->s_port; } else { lport = htons(ntohs(PW_ACCT_UDP_PORT)); } } } if ((hostent = gethostbyname(host_name)) == (struct hostent *)NULL) { fprintf(stderr, "gethostbyname<%s> error<%d>\n", host_name, errno); exit(1); } memcpy( &addr.sin_addr.s_addr, hostent->h_addr, hostent->h_length); host = ntohl(addr.sin_addr.s_addr); addr.sin_family = AF_INET; addr.sin_port = lport; printf("Radius client: server is host: %s %s Port: %d\n", host_name, inet_ntoa(addr.sin_addr), ntohs(lport)); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(errno); } /* * build packet and send it */ ah = (AUTH_HDR *)s_buf; memset(ah, 0, sizeof(*ah)); if (acct_flag) { ah->code = PW_ACCOUNTING_REQUEST; } else { ah->code = PW_AUTHENTICATION_REQUEST; } ah->id = id; len = AUTH_HDR_LEN; u_name_len = strlen(u_name); u_passwd_len = strlen(u_passwd); /* * user name is mandatory */ cp = ah->data; *cp++ = PW_USER_NAME; *cp++ = u_name_len + 2; memcpy(cp, u_name, u_name_len); cp += u_name_len; len += u_name_len + 2; /* * password doesn't handle longer than 16 characters, for now */ if (passwd && service_type != PW_CALL_CHECK_USER ) { *cp++ = PW_PASSWORD; *cp++ = AUTH_PASS_LEN + 2; if (u_passwd_len > AUTH_PASS_LEN) { u_passwd_len = AUTH_PASS_LEN; } memset(passwd, 0, AUTH_PASS_LEN); memcpy(passwd, u_passwd, u_passwd_len); strcpy(md5_buf, secret); memcpy(md5_buf + secret_len, ah->vector, AUTH_VECTOR_LEN); md5_calc(cp, md5_buf, secret_len + AUTH_VECTOR_LEN); for (i = 0; i < AUTH_PASS_LEN; i++) { *cp++ ^= passwd[i]; } len += AUTH_PASS_LEN + 2; } /* * client id */ alen = 4; *cp++ = PW_CLIENT_ID; *cp++ = alen + 2; val = htonl(0x7f000001); /* 127.0.0.1 */ memcpy(cp, &val, alen); cp += alen; len += alen + 2; /* * client port id */ alen = 4; *cp++ = PW_CLIENT_PORT_ID; *cp++ = alen + 2; val = htonl(1); memcpy(cp, &val, alen); cp += alen; len += alen + 2; /* * framed hint */ if (service_type) { alen = 4; *cp++ = PW_USER_SERVICE_TYPE; *cp++ = alen + 2; val = htonl(service_type); memcpy(cp, &val, alen); cp += alen; len += alen + 2; } else if (frame_flag) { alen = 4; *cp++ = PW_USER_SERVICE_TYPE; *cp++ = alen + 2; val = htonl(PW_FRAMED_USER); memcpy(cp, &val, alen); cp += alen; len += alen + 2; alen = 4; *cp++ = PW_FRAMED_PROTOCOL; *cp++ = alen + 2; val = htonl(PW_PPP); memcpy(cp, &val, alen); cp += alen; len += alen + 2; } /* * called station id */ if (called_id) { alen = (u_char)strlen(called_id); *cp++ = PW_CALLED; *cp++ = alen + 2; memcpy(cp, called_id, alen); cp += alen; len += alen + 2; } /* * calling station id */ if (calling_id) { alen = (u_char)strlen(calling_id); *cp++ = PW_CALLING; *cp++ = alen + 2; memcpy(cp, calling_id, alen); cp += alen; len += alen + 2; } ah->length = htons(len); if (acct_flag) { /* sign it */ /* STUB */ } if ((rc = sendto(fd, (char *)ah, len, 0, (struct sockaddr *)&addr, sizeof addr)) < 0) { perror("sendto: "); rad_exit(errno); } FD_ZERO(&fdset); FD_SET(fd, &fdset); tv.tv_sec = 5; tv.tv_usec = 0; if (select(32, &fdset, NULL, NULL, &tv) < 0) { perror("select: "); rad_exit(errno); } if (FD_ISSET(fd, &fdset)) { sa_len = sizeof sa_ihd; if ((rc = recvfrom(fd, r_buf, sizeof r_buf, 0, (struct sockaddr *)&sa_ihd, &sa_len)) < 0) { perror("recvfrom: "); rad_exit(errno); } } else { printf("recv timeout\n"); rad_exit(errno); } /* STUB - does not check response authenticator yet */ ah = (AUTH_HDR *)r_buf; switch(ah->code) { case PW_AUTHENTICATION_ACK: printf("Received Accept\n"); break; case PW_AUTHENTICATION_REJECT: printf("Received Reject\n"); break; case PW_ACCESS_CHALLENGE: printf("Received Challenge\n"); break; case PW_ACCOUNTING_RESPONSE: printf("Received Accounting Response\n"); break; default: printf("ERROR Received code %d id %d length %d\n", ah->code, ah->id, ah->length); return; break; } authreq = radrecv(host, ntohs(lport), secret, r_buf, rc); if (authreq != (AUTH_REQ *)NULL) { pair = authreq->request; while (pair != (VALUE_PAIR *)NULL) { fputs("\t", stdout); fprint_attr_val(stdout, pair); fputs("\n", stdout); pair = pair->next; } } close(fd); } /************************************************************************* * * Function: radrecv * * Purpose: Receive UDP client requests, build an authorization request * structure, and attach attribute-value pairs contained in * the request to the new structure. * *************************************************************************/ AUTH_REQ * radrecv(host, udp_port, secret, buffer, length) UINT4 host; u_short udp_port; char *secret; u_char *buffer; int length; { u_char *ptr; char *bufalloc(); AUTH_HDR *auth; int totallen; int attribute; int attrlen; int vendor; int vsa; int vsattrlen; DICT_ATTR *attr; DICT_ATTR *dict_attrget(); DICT_ATTR *dict_vsattrget(); UINT4 lvalue; VALUE_PAIR *first_pair; VALUE_PAIR *prev; VALUE_PAIR *pair; VALUE_PAIR *pairalloc(); AUTH_REQ *authreq; AUTH_REQ *reqalloc(); void hexdump(); void pairfree(); void rad_exit(); void reqfree(); if (length < AUTH_HDR_LEN) { /* too short to be real */ log_err("radrecv: runt packet of %d bytes from %s/%d\n", length, ipaddr2strp(host), udp_port); return ((AUTH_REQ *)NULL); } /* * Pre-allocate the new request data structure */ authreq = reqalloc("radrecv"); auth = (AUTH_HDR *)buffer; totallen = ntohs(auth->length); if (totallen > length) { /* truncated packet, ignore */ log_err("radrecv: message from %s/%d claimed length %d, only %d bytes received\n", ipaddr2strp(host), udp_port, totallen, length); reqfree(authreq,"radrecv"); return((AUTH_REQ *)NULL); } DEBUG("message received from %s/%d.%d code=%d, length=%d\n", ipaddr2strp(host), udp_port, auth->id, auth->code, totallen); if (debug_flag > 1) { hexdump(buffer,totallen); } /* * Fill header fields */ authreq->ipaddr = host; authreq->udp_port = udp_port; authreq->id = auth->id; authreq->code = auth->code; memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN); strncpy(authreq->secret,secret,20); authreq->secret[19]='\0'; /* * Extract attribute-value pairs */ ptr = auth->data; length = totallen - AUTH_HDR_LEN; first_pair = (VALUE_PAIR *)NULL; prev = (VALUE_PAIR *)NULL; while(length > 0) { attribute = *ptr++; attrlen = *ptr++; if(attrlen < 2) { length = 0; continue; } attrlen -= 2; if ( attrlen > AUTH_STRING_LEN ) { log_err("radrecv: attribute %d from %s too long, length of %d > %d\n", attribute, req2strp(authreq), attrlen, AUTH_STRING_LEN); reqfree(authreq,"radrecv"); return((AUTH_REQ *)NULL); } pair = pairalloc("radrecv"); if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) { sprintf(pair->name,"Unknown-%d",attribute); pair->attribute = attribute; pair->type = PW_TYPE_STRING; } else { strcpy(pair->name, attr->name); pair->attribute = attr->value; pair->type = attr->type; } if (pair->attribute == PW_VENDOR) { if (attrlen < 6 || ((vsattrlen = *(ptr+5)) != (attrlen-4))) { pair->vendor = 0; pair->vsattribute = 0; pair->type = PW_TYPE_STRING; } else { memcpy(&vendor, ptr, sizeof(UINT4)); vendor = ntohl(vendor); ptr += 4; vsa = *ptr++; attrlen = vsattrlen - 2; ptr++; length -= 6; pair->vendor = vendor; pair->vsattribute = vsa; if((attr = dict_vsattrget(vendor,vsa)) != (DICT_ATTR *)NULL) { strcpy(pair->name, attr->name); pair->type = attr->type; } else { sprintf(pair->name,"Vendor-Specific-%d-%d",vendor,vsa); pair->type = PW_TYPE_STRING; } } } switch(pair->type) { case PW_TYPE_STRING: memcpy(pair->strvalue, ptr, attrlen); pair->strvalue[attrlen] = '\0'; pair->lvalue = attrlen; if(first_pair == (VALUE_PAIR *)NULL) { first_pair = pair; } else { prev->next = pair; } prev = pair; break; case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: memcpy(&lvalue, ptr, sizeof(UINT4)); pair->lvalue = ntohl(lvalue); if(first_pair == (VALUE_PAIR *)NULL) { first_pair = pair; } else { prev->next = pair; } prev = pair; break; default: DEBUG(" %s (Unknown Type %d)\n", attr->name,attr->type); pairfree(pair,"radrecv"); break; } ptr += attrlen; length -= attrlen + 2; } authreq->request = first_pair; authreq->timestamp = now; /* now was set in main() */ /* copy the packet */ authreq->packet = bufalloc(totallen,"radrecv"); memcpy(authreq->packet,buffer,totallen); return(authreq); } void usage() { printf("usage: %s -d called_id -f -g calling_id -h -i id -p port -s secret -t type -v -x -u username password\n", progname); exit(0); } void rad_exit(rc) int rc; { exit(rc); } void version() { printf("%s 1.0 1999/6/15\n", progname); exit(0); } radiusd-livingston-2.1/src/securid.c0100644000175000017500000001653706734270174015433 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: securid.c,v 1.12 1999/06/23 23:40:44 cdr Exp $ Copyright 1995-1999 Lucent Technologies Inc"; #include #include #include #include "radius.h" /* To compile this source you will need to get the header files * distributed with SecurID by Security Dynamics */ #include "sdi_athd.h" #include "sdi_defs.h" #include "sdi_size.h" #include "sdi_type.h" #include "sdacmvls.h" #include "sdconf.h" union config_record configure; struct SD_CLIENT sd_dat; #define CANCELLED 1 int securid(username, password, authreq, user_reply, activefd) char *username; char *password; AUTH_REQ *authreq; VALUE_PAIR *user_reply; int activefd; { struct SD_CLIENT *sd_p; int retcode; VALUE_PAIR *attr; VALUE_PAIR *get_attribute(); static int securid_active; int creadcfg(); int challenge; int sd_check(); int sd_close(); int sd_init(); int sd_next(); int sd_pin(); char msg[256]; char pintype[16]; char pinsize[16]; char state_value[128]; pid_t getpid(); void pairfree(); void reqfree(); void send_accept(); void send_reject(); void send_challenge(); sd_p = &sd_dat; if(securid_active != 1) { /* clear struct */ memset((u_char *)sd_p, 0, sizeof(sd_dat)); /* accesses sdconf.rec */ if (creadcfg()) { log_err("securid: error reading sdconf.rec\n"); reqfree(authreq,"securid"); pairfree(user_reply,"securid"); return(0); } if(sd_init(sd_p)) { log_err("securid: cannot initialize connection to SecurID server\n"); reqfree(authreq,"securid"); pairfree(user_reply,"securid"); return(0); } securid_active = 1; } /* * In some cases, SecurID will require two Cardcodes to properly * authenticate. When it wants a second one, we will store the * SD_CLIENT data so we have state. The scond time around (after * the challenge) we will have what we need to use sd_next(). * This keeps us stateless. */ attr = get_attribute(authreq->request, PW_STATE); if (attr != (VALUE_PAIR *)NULL) { if (strncmp(attr->strvalue, "SECURID_NEXT=", 13) == 0){ strcpy(sd_p->username, username); retcode = sd_next(password, sd_p); DEBUG("securid: sd_next retcode=%d\n", retcode); } else if (strncmp(attr->strvalue, "SECURID_NPIN=", 13) == 0){ strcpy(sd_p->username, username); retcode = sd_pin(password, 0, sd_p); DEBUG("securid: sd_pin retcode=%d\n", retcode); } else if (strncmp(attr->strvalue, "SECURID_WAIT=", 13) == 0){ send_reject(authreq,"Log in with new PIN and code.\r\n",activefd); reqfree(authreq,"securid"); pairfree(user_reply,"securid"); sd_close(); securid_active = 0; return(0); } else { log_err("securid: unexpected STATE=\"%s\"\n",attr->strvalue); retcode = -1; } } else { /* The following line removed in 2.0.1 to enable SDI to function properly */ /* memset(sd_p, 0, sizeof(sd_dat)); */ retcode = sd_check(password, username, sd_p); DEBUG("securid: sd_check retcode=%d\n", retcode); } challenge = 0; switch (retcode) { case ACM_OK: send_accept(authreq, user_reply, (char *)NULL, activefd); break; case ACM_ACCESS_DENIED: send_reject(authreq, (char *)NULL, activefd); break; case ACM_NEXT_CODE_REQUIRED: challenge = 1; sprintf(state_value, "SECURID_NEXT=%lu", (UINT4)getpid()); send_challenge(authreq, "Enter next Cardcode: ", state_value, activefd); break; case ACM_NEW_PIN_REQUIRED: if (sd_p->user_selectable == CANNOT_CHOOSE_PIN) { if (sd_pin(sd_p->system_pin, 0, sd_p) == ACM_NEW_PIN_ACCEPTED) { challenge = 1; sprintf(msg,"%s is your new PIN. Press RETURN to disconnect, wait for token\r\n code to change, log in with new PIN and code.\r\n",sd_p->system_pin); sprintf(state_value, "SECURID_WAIT=%u", (unsigned int)getpid()); send_challenge(authreq,msg,state_value,activefd); } else { send_reject(authreq,"PIN rejected. Please try again.\r\n",activefd); } } else if (sd_p->user_selectable == USER_SELECTABLE || sd_p->user_selectable == MUST_CHOOSE_PIN) { challenge = 1; sprintf(state_value, "SECURID_NPIN=%u", (unsigned int)getpid()); if (sd_p->alphanumeric) strcpy(pintype, "characters"); else strcpy(pintype, "digits"); if (sd_p->min_pin_len == sd_p->max_pin_len) sprintf(pinsize, "%d", sd_p->min_pin_len); else sprintf(pinsize, "%d to %d", sd_p->min_pin_len, sd_p->max_pin_len); sprintf(msg,"Enter your new PIN, containing %s %s:", pinsize,pintype); send_challenge(authreq, msg, state_value, activefd); } else { log_err("securid: New Pin required but user select has unknown value %d, sending reject\n",sd_p->user_selectable); send_reject(authreq,(char *)NULL,activefd); } break; case ACM_NEW_PIN_ACCEPTED: send_reject(authreq,"New Pin Accepted.\r\nWait for next card code and then login.\r\n", activefd); break; case -1: send_reject(authreq, (char *)NULL, activefd); break; default: log_err("securid: SecurID server returned unknown code %d for user %s\n", retcode, username); send_reject(authreq, (char *)NULL, activefd); break; } reqfree(authreq,"securid"); pairfree(user_reply,"securid"); /* The following line added in 2.0.1 so that the connection between RADIUS * and SDI is broken after each request, as it should according to SDI. */ if(challenge==0) { sd_close(); securid_active = 0; } return(challenge); } int __ansi_fflush(f) FILE *f; { int fflush(); return fflush(f); } radiusd-livingston-2.1/src/testuser.c0100644000175000017500000001010106734270174015630 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /* * testuser - test program to retrieve an entry from the user table */ static char sccsid[] = "$Id: testuser.c,v 1.6 1999/06/23 23:40:44 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include "radius.h" #include "users.h" #include char *progname; int debug_flag; int radius_dbm; char *radius_dir; char *radius_log; int accept_zero = 0; int debug_mem = 0; int main(argc, argv) int argc; char * argv[]; { USER_DESC *user_desc; VALUE_PAIR *user_check; VALUE_PAIR *user_reply; char auth_name[AUTH_STRING_LEN + 2]; char *req_name; int dict_init(); int i; void dump_pair(); void log_version(); void pairfree(); void usage(); debug_flag = 1; radius_dbm = 0; req_name = (char *)NULL; for (i=1; i NOT Found!\n", req_name); break; } printf("Found user req_name <%s> auth_name <%s>\n", req_name, auth_name); dump_pair(user_reply); pairfree(user_check,"main"); pairfree(user_reply,"main"); } user_close(user_desc); exit(0); } void dump_pair(vp) VALUE_PAIR * vp; { while (vp) { if (vp->attribute == PW_PORT_MESSAGE) { printf(" from %s\n", vp->strvalue); } vp = vp->next; } } void usage() { printf("usage: testuser \n"); exit(1); } VALUE_PAIR * get_attribute(value_list, attribute) VALUE_PAIR *value_list; int attribute; { while(value_list != (VALUE_PAIR *)NULL) { if(value_list->attribute == attribute) { return(value_list); } value_list = value_list->next; } return((VALUE_PAIR *)NULL); } void rad_exit(rc) int rc; { exit(rc); } radiusd-livingston-2.1/src/users.c0100644000175000017500000004211006734270174015120 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: users.c,v 1.28 1999/06/23 23:40:44 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include #include #include int db_index; #include "radius.h" #include "users.h" #define MAXBUF 1024 extern char *progname; extern int debug_flag; extern int errno; extern int radius_dbm; extern char *radius_dir; static void fieldcpy(); int userparse(); #define FIND_MODE_NAME 0 #define FIND_MODE_REPLY 1 #define FIND_MODE_SKIP 2 #define FIND_MODE_FLUSH 3 /************************************************************************* * * Function: user_find * * Purpose: Find the named user in the database. Create the * set of attribute-value pairs to check and reply with * for this user from the database. * *************************************************************************/ int user_find(req_name, auth_name, check_pairs, reply_pairs, user_desc) char *req_name; char *auth_name; VALUE_PAIR **check_pairs; VALUE_PAIR **reply_pairs; USER_DESC *user_desc; { VALUE_PAIR *check_first; VALUE_PAIR *reply_first; char *ptr; char buffer[MAXBUF]; datum contentd; datum named; int mode; int req_namelen; int user_auth_name(); time_t time(); void pairfree(); /* * Check for valid input, zero length names not permitted */ mode = FIND_MODE_NAME; ptr=req_name; while (*ptr != '\0') { if (*ptr == ' ' || *ptr == '\t') { #ifdef SPACECHOP *ptr = '\0'; #else log_err("user_find: space in username \"%s\" rejected\n",req_name); return(-1); #endif } else { ptr++; } } req_namelen=strlen(req_name); if (req_namelen < 1) { log_err("user_find: zero length username rejected\n"); return(-1); } check_first = (VALUE_PAIR *)NULL; reply_first = (VALUE_PAIR *)NULL; if (radius_dbm != 0) { for (;;) { if (db_index == -1) { named.dptr = req_name; named.dsize = strlen(req_name); } else if (db_index == 0) { sprintf(buffer, "DEFAULT"); named.dptr = buffer; named.dsize = strlen(buffer); } else { sprintf(buffer, "DEFAULT%d", db_index); named.dptr = buffer; named.dsize = strlen(buffer); } db_index++; #ifdef NDBM contentd = dbm_fetch(user_desc, named); #else /* not NDBM */ contentd = fetch(named); #endif /* NDBM */ if(contentd.dsize == 0) { if (db_index == 0) { /* * the request id failed * lets try the defaults */ continue; } return(-1); } /* * Parse the check values */ if (contentd.dsize > MAXBUF) { log_err("user_find: user record for user %s is too big, %d exceeds %d\n", req_name,contentd.dsize,MAXBUF); return(-1); } memcpy(buffer,contentd.dptr,contentd.dsize); buffer[contentd.dsize] = '\0'; ptr = buffer; if(userparse(ptr, &check_first) != 0) { log_err("user_find: unable to parse check-items in dbm entry for user %s\n", req_name); pairfree(check_first,"user_find"); return(-1); } /* * set authentication name */ if (user_auth_name( req_name, auth_name, check_first) != 0) { pairfree(check_first,"user_find"); check_first = (VALUE_PAIR *)NULL; continue; } break; } while(*ptr != '\n' && *ptr != '\0') { ptr++; } if(*ptr == '\0') { /* no reply-items */ *check_pairs = check_first; *reply_pairs = (VALUE_PAIR *)NULL; return(0); } ptr++; /* * Parse the reply values */ if(userparse(ptr, &reply_first) != 0) { log_err("user_find: unable to parse reply-items in dbm entry for user %s\n", req_name); pairfree(check_first,"user_find"); pairfree(reply_first,"user_find"); return(-1); } } else { while(fgets(buffer, sizeof(buffer), (FILE *)user_desc) != (char *)NULL) { if(mode == FIND_MODE_NAME) { /* * Find the entry starting with the users name */ if((strncmp(buffer, req_name, req_namelen) == 0 && (buffer[req_namelen] == ' ' || buffer[req_namelen] == '\t')) || strncmp(buffer, "DEFAULT", 7) == 0) { if(strncmp(buffer, "DEFAULT", 7) == 0) { ptr = &buffer[7]; /* * advance pointer to next white space */ while (isspace(*ptr) == 0) { ptr++; } } else { ptr = &buffer[req_namelen]; } /* * Parse the check values */ if(userparse(ptr, &check_first) != 0) { log_err("user_find: unable to parse check-items for user %s\n", req_name); pairfree(check_first,"user_find"); return(-1); } /* * set authentication name */ if (user_auth_name( req_name, auth_name, check_first) != 0) { pairfree(check_first,"user_find"); check_first = (VALUE_PAIR *)NULL; continue; } mode = FIND_MODE_REPLY; } } else { if(*buffer == ' ' || *buffer == '\t') { /* * Parse the reply values */ if(userparse(buffer, &reply_first) != 0) { log_err("user_find: unable to parse reply-items for user %s\n", req_name); pairfree(check_first,"user_find"); pairfree(reply_first,"user_find"); return(-1); } } else { /* We are done */ *check_pairs = check_first; *reply_pairs = reply_first; return(0); } } } } /* Update the callers pointers */ if(reply_first != (VALUE_PAIR *)NULL) { *check_pairs = check_first; *reply_pairs = reply_first; return(0); } return(-1); } /************************************************************************* * * Function: user_auth_name * * Purpose: Set authentication name, stripping pre/suffix * *************************************************************************/ int user_auth_name(rname, auth_name, check_first) char *rname; char *auth_name; VALUE_PAIR *check_first; { VALUE_PAIR *fix; VALUE_PAIR *get_attribute(); int req_len; int len; char namebuf[AUTH_STRING_LEN+2]; char *req_name; req_len = strlen(rname); req_name = namebuf; if (req_len > AUTH_STRING_LEN) { req_len = AUTH_STRING_LEN; req_name[req_len] = '\0'; } strncpy(req_name, rname, req_len); if ((fix = get_attribute(check_first, PW_PREFIX)) != (VALUE_PAIR *)NULL) { len = strlen(fix->strvalue); if (req_len <= len || (strncmp(req_name, fix->strvalue, len) != 0)) { return(-1); } /* * strip prefix from request name */ req_name += len; req_len -= len; } if ((fix = get_attribute(check_first, PW_SUFFIX)) != (VALUE_PAIR *)NULL) { len = strlen(fix->strvalue); if (req_len <= len || (strncmp(&req_name[req_len - len], fix->strvalue, len) != 0)) { return(-1); } /* * strip suffix from request name */ req_len -= len; } strncpy(auth_name, req_name, req_len); auth_name[req_len] = '\0'; return(0); } #define PARSE_MODE_NAME 0 #define PARSE_MODE_EQUAL 1 #define PARSE_MODE_VALUE 2 #define PARSE_MODE_INVALID 3 /************************************************************************* * * Function: userparse * * Purpose: Parses the buffer to extract the attribute-value pairs. * *************************************************************************/ int userparse(buffer, first_pair) char *buffer; VALUE_PAIR **first_pair; { int mode; int atoi(); char attrstr[64]; char valstr[256]; DICT_ATTR *attr; DICT_ATTR *dict_attrfind(); DICT_VALUE *dval; DICT_VALUE *dict_valfind(); VALUE_PAIR *pair; VALUE_PAIR *link; VALUE_PAIR *pairalloc(); UINT4 ipstr2long(); UINT4 get_ipaddr(); int user_gettime(); struct tm *tm; time_t timeval; time_t time(); #ifdef TIMELOCAL time_t timelocal(); #else time_t mktime(); #endif mode = PARSE_MODE_NAME; while(*buffer != '\n' && *buffer != '\0') { if(*buffer == ' ' || *buffer == '\t' || *buffer == ',') { buffer++; continue; } switch(mode) { case PARSE_MODE_NAME: /* Attribute Name */ fieldcpy(attrstr, &buffer); if((attr = dict_attrfind(attrstr)) == (DICT_ATTR *)NULL) { return(-1); } mode = PARSE_MODE_EQUAL; break; case PARSE_MODE_EQUAL: /* Equal sign */ if(*buffer == '=') { mode = PARSE_MODE_VALUE; buffer++; } else { return(-1); } break; case PARSE_MODE_VALUE: /* Value */ fieldcpy(valstr, &buffer); pair = pairalloc("userparse"); strcpy(pair->name, attr->name); pair->attribute = attr->value; pair->type = attr->type; pair->vendor = attr->vendor; pair->vsattribute = attr->vsvalue; switch(pair->type) { case PW_TYPE_STRING: strcpy(pair->strvalue, valstr); pair->lvalue = strlen(valstr); break; case PW_TYPE_INTEGER: if(isdigit(*valstr)) { pair->lvalue = atoi(valstr); } else if((dval = dict_valfind(valstr)) == (DICT_VALUE *)NULL) { free(pair); return(-1); } else { pair->lvalue = dval->value; } break; case PW_TYPE_IPADDR: pair->lvalue = get_ipaddr(valstr); break; case PW_TYPE_DATE: timeval = time(0); tm = localtime(&timeval); if (user_gettime(valstr, tm) < 0) { pair->lvalue = 0; log_err("invalid expiration format \"%s\" rejected\n",valstr); } else { #ifdef TIMELOCAL pair->lvalue = (UINT4)timelocal(tm); #else /* TIMELOCAL */ pair->lvalue = (UINT4)mktime(tm); #endif /* TIMELOCAL */ } break; default: free(pair); return(-1); } pair->next = (VALUE_PAIR *)NULL; if(*first_pair == (VALUE_PAIR *)NULL) { *first_pair = pair; } else { link = *first_pair; while(link->next != (VALUE_PAIR *)NULL) { link = link->next; } link->next = pair; } mode = PARSE_MODE_NAME; break; default: mode = PARSE_MODE_NAME; break; } } return(0); } /************************************************************************* * * Function: fieldcpy * * Purpose: Copy a data field from the buffer. Advance the buffer * past the data field. * *************************************************************************/ static void fieldcpy(string, uptr) char *string; char **uptr; { char *ptr; ptr = *uptr; if(*ptr == '"') { ptr++; while(*ptr != '"' && *ptr != '\0' && *ptr != '\n') { *string++ = *ptr++; } *string = '\0'; if(*ptr == '"') { ptr++; } *uptr = ptr; return; } while(*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' && *ptr != '=' && *ptr != ',') { *string++ = *ptr++; } *string = '\0'; *uptr = ptr; return; } #ifdef PASSCHANGE /************************************************************************* * * Function: user_update * * Purpose: Updates a user in the database. Replaces the original * entry with the name, the list of check items, and the * list of reply items which are supplied. * *************************************************************************/ int user_update(name, user_check, user_reply) char *name; VALUE_PAIR *user_check; VALUE_PAIR *user_reply; { FILE *oldfd; FILE *userfd; char buffer[256]; char oldfile[256]; char newfile[256]; int namelen; int mode; void fprint_attr_val(); sprintf(oldfile, "%s/%s", radius_dir, RADIUS_USERS); sprintf(newfile, "%s/%s", radius_dir, RADIUS_HOLD); /* Open the old user file */ if((oldfd = fopen(oldfile, "r")) == (FILE *)NULL) { log_err("user_update: could not read users file %s\n",oldfile); return(-1); } /* Open the new user file */ if((userfd = fopen(newfile, "w")) == (FILE *)NULL) { log_err("user_update: could not write to %s\n", newfile); fclose(oldfd); return(-1); } mode = FIND_MODE_NAME; namelen = strlen(name); /* Copy the old to the new, only recreating the changed user */ while(fgets(buffer, sizeof(buffer), oldfd) != (char *)NULL) { if(mode == FIND_MODE_NAME) { if((strncmp(buffer, name, namelen) == 0 && (buffer[namelen] == ' ' || buffer[namelen] == '\t'))) { /* Write our new information */ fprintf(userfd, "%s\t", name); while(user_check != (VALUE_PAIR *)NULL) { fprint_attr_val(userfd, user_check); if(user_check->next != (VALUE_PAIR *)NULL) { fprintf(userfd, ", "); } user_check = user_check->next; } fprintf(userfd, "\n\t"); while(user_reply != (VALUE_PAIR *)NULL) { fprint_attr_val(userfd, user_reply); if(user_reply->next != (VALUE_PAIR *)NULL) { fprintf(userfd, ",\n\t"); } user_reply = user_reply->next; } fprintf(userfd, "\n"); mode = FIND_MODE_SKIP; } else { fputs(buffer, userfd); } } else if(mode == FIND_MODE_SKIP) { if(*buffer != ' ' && *buffer != '\t') { fputs(buffer, userfd); mode = FIND_MODE_FLUSH; } } else { fputs(buffer, userfd); } } fclose(oldfd); fclose(userfd); if (rename(newfile,oldfile) != 0) { log_err("user_update: unable to rename %s to %s after updating user %s; error %d\n",newfile,oldfile,name,errno); return(-1); } return(0); } #endif /* PASSCHANGE */ /************************************************************************* * * Function: user_gettime * * Purpose: Turns printable string into correct tm struct entries * *************************************************************************/ static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; int user_gettime(valstr, tm) char *valstr; struct tm *tm; { int i; int atoi(); /* Get the month */ for(i = 0;i < 12;i++) { if(strncmp(months[i], valstr, 3) == 0) { tm->tm_mon = i; i = 13; } } /* Get the Day */ tm->tm_mday = atoi(&valstr[4]); /* Now the year */ tm->tm_year = atoi(&valstr[7]) - 1900; /* Midnight */ tm->tm_sec = 0; tm->tm_min = 0; tm->tm_hour = 0; /* if date makes no sense return failure */ if (i == 12 || tm->tm_mday < 1 || tm->tm_mday > 31 || tm->tm_year < 70) { return(-1); } else { return(0); } } /************************************************************************* * * Function: user_open * * Purpose: open the users file * *************************************************************************/ USER_DESC * user_open(void) { USER_DESC *user_desc; char buffer[1024]; extern FILE *user_open_flat(char *); sprintf(buffer, "%s/%s", radius_dir, RADIUS_USERS); if (radius_dbm == 0) { return( (USER_DESC *)user_open_flat(buffer) ); } # ifdef NDBM if((user_desc = dbm_open(buffer, O_RDONLY, 0)) == (USER_DESC *)NULL) # else /* not NDBM */ if(dbminit(buffer) != 0) # endif /* NDBM */ { log_err("user_open: could not read user dbm file %s\n", buffer); return((USER_DESC *)NULL); } db_index = -1; return(user_desc); } FILE * user_open_flat(file_name) char *file_name; { FILE *user_desc; /* * Open the user table */ if((user_desc = fopen(file_name, "r")) == (FILE *)NULL) { log_err("user_open: could not read user file %s\n", file_name); return((FILE *)NULL); } return(user_desc); } /************************************************************************* * * Function: user_close * * Purpose: close the users file * *************************************************************************/ void user_close(user_desc) USER_DESC *user_desc; { if (radius_dbm != 0) { # ifdef NDBM dbm_close(user_desc); # else /* not NDBM */ dbmclose(); # endif /* NDBM */ } else { fclose((FILE *)user_desc); } } radiusd-livingston-2.1/src/users.h0100644000175000017500000000464006734270174015133 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /* * $Id: users.h,v 1.7 1999/06/23 23:40:44 cdr Exp $ %Y% */ # ifdef NDBM # include # include # else /* not NDBM */ # include # endif /* NDBM */ # define USER_DESC DBM extern USER_DESC *user_open ( void); extern void user_close ( USER_DESC *user_desc); extern int user_find ( char *req_name, char *auth_name, VALUE_PAIR **check_pairs, VALUE_PAIR **reply_pairs, USER_DESC *userfd); radiusd-livingston-2.1/src/util.c0100644000175000017500000003767606734270175014762 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: util.c,v 1.12 1999/06/23 23:40:45 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include #include #include #include #include #include #include "radius.h" /* Memory structures allocated, for debugging purposes */ int hmembuf = 0; /* highwater marks */ int hmempair = 0; int hmempeer = 0; int hmemreq = 0; int nmembuf = 0; /* number allocated but not freed */ int nmempair = 0; int nmempeer = 0; int nmemreq = 0; int tmembuf = 0; /* total number allocated */ int tmempair = 0; int tmempeer = 0; int tmemreq = 0; extern int debug_mem; /************************************************************************* * * Function: ip_hostname * * Purpose: Return a printable host name (or IP address in dot notation) * for the supplied IP address. * *************************************************************************/ char * ip_hostname(ipaddr) UINT4 ipaddr; { struct hostent *hp; static char hstname[128]; UINT4 n_ipaddr; void ipaddr2str(); n_ipaddr = htonl(ipaddr); hp = gethostbyaddr((char *)&n_ipaddr, sizeof (struct in_addr), AF_INET); if (hp == 0) { ipaddr2str(hstname, ipaddr); return(hstname); } return(hp->h_name); } /************************************************************************* * * Function: get_ipaddr * * Purpose: Return an IP address in host long notation from a host * name or address in dot notation. * *************************************************************************/ UINT4 get_ipaddr(host) char *host; { struct hostent *hp; UINT4 ipstr2long(); int good_ipaddr(); if(good_ipaddr(host) == 0) { return(ipstr2long(host)); } else if((hp = gethostbyname(host)) == (struct hostent *)NULL) { return((UINT4)0); } return(ntohl(*(UINT4 *)hp->h_addr)); } /************************************************************************* * * Function: good_ipaddr * * Purpose: Check for valid IP address in standard dot notation. * *************************************************************************/ int good_ipaddr(addr) char *addr; { int dot_count; int digit_count; dot_count = 0; digit_count = 0; while(*addr != '\0' && *addr != ' ') { if(*addr == '.') { dot_count++; digit_count = 0; } else if(!isdigit(*addr)) { dot_count = 5; } else { digit_count++; if(digit_count > 3) { dot_count = 5; } } addr++; } if(dot_count != 3) { return(-1); } else { return(0); } } /************************************************************************* * * Function: ipaddr2str * * Purpose: Return an IP address in standard dot notation for the * provided address in host long notation. * *************************************************************************/ void ipaddr2str(buffer, ipaddr) char *buffer; UINT4 ipaddr; { int addr_byte[4]; int i; UINT4 xbyte; for(i = 0;i < 4;i++) { xbyte = ipaddr >> (i*8); xbyte = xbyte & (UINT4)0x000000FF; addr_byte[i] = xbyte; } sprintf(buffer, "%u.%u.%u.%u", addr_byte[3], addr_byte[2], addr_byte[1], addr_byte[0]); } /************************************************************************* * * Function: ipaddr2strp * * Purpose: Return an IP address in standard dot notation for the * provided address in host long notation. * *************************************************************************/ char * ipaddr2strp(ipaddr) UINT4 ipaddr; { int addr_byte[4]; int i; UINT4 xbyte; static char buffer[32]; for(i = 0;i < 4;i++) { xbyte = ipaddr >> (i*8); xbyte = xbyte & (UINT4)0x000000FF; addr_byte[i] = xbyte; } sprintf(buffer, "%u.%u.%u.%u", addr_byte[3], addr_byte[2], addr_byte[1], addr_byte[0]); return(buffer); } /************************************************************************* * * Function: ipstr2long * * Purpose: Return an IP address in host long notation from * one supplied in standard dot notation. * *************************************************************************/ UINT4 ipstr2long(ip_str) char *ip_str; { char buf[6]; char *ptr; int i; int count; UINT4 ipaddr; int cur_byte; int atoi(); ipaddr = (UINT4)0; for(i = 0;i < 4;i++) { ptr = buf; count = 0; *ptr = '\0'; while(*ip_str != '.' && *ip_str != '\0' && count < 4) { if(!isdigit(*ip_str)) { return((UINT4)0); } *ptr++ = *ip_str++; count++; } if(count >= 4 || count == 0) { return((UINT4)0); } *ptr = '\0'; cur_byte = atoi(buf); if(cur_byte < 0 || cur_byte > 255) { return((UINT4)0); } ip_str++; ipaddr = ipaddr << 8 | (UINT4)cur_byte; } return(ipaddr); } /************************************************************************* * * Function: req2str * req2strp * * Purpose: Return an IP address in standard dot notation, * followed by / port . id, for the provided authreq * *************************************************************************/ char * req2str(buffer,authreq) char *buffer; AUTH_REQ *authreq; { int addr_byte[4]; int i; UINT4 xbyte; UINT4 ipaddr; if (buffer == (char *)NULL) { return buffer; } if (authreq == (AUTH_REQ *)NULL) { memcpy(buffer,"(unidentified)",15); return (buffer); } ipaddr = authreq->ipaddr; for(i = 0;i < 4;i++) { xbyte = ipaddr >> (i*8); xbyte = xbyte & (UINT4)0x000000FF; addr_byte[i] = xbyte; } sprintf(buffer, "%u.%u.%u.%u/%u.%u", addr_byte[3], addr_byte[2], addr_byte[1], addr_byte[0], authreq->udp_port, authreq->id); return(buffer); } char * req2strp(authreq) AUTH_REQ *authreq; { static char buffer[32]; return req2str(buffer,authreq); } /************************************************************************* * * Function: bufalloc * * Purpose: Allocate memory for use by a buffer * *************************************************************************/ char * bufalloc(size,where) int size; char *where; { extern int hmembuf; extern int nmembuf; extern int tmembuf; extern int debug_mem; char *buf; void rad_exit(); if((buf = (char *)malloc((unsigned)size)) == (char *)NULL) { log_err("%s: fatal system error: out of memory, exiting\n",where); rad_exit(-1); } /* no need to zero buffer since we'll be copying into it */ nmembuf++; tmembuf++; if (nmembuf > hmembuf) { hmembuf = nmembuf; } if (debug_mem) { log_err("called bufalloc(%d,%s) = %x %d\n",size,where,(int)buf,nmembuf); } return buf; } /************************************************************************* * * Function: buffree * * Purpose: Release the memory allocated by bufalloc(); * *************************************************************************/ void buffree(buf,where) char *buf; char *where; { extern int nmembuf; extern int debug_mem; if (debug_mem) { log_err("called buffree(%x,%s) = %d\n",(int)buf,where,nmembuf); } if (buf == (char *)NULL) { log_err("%s called buffree with NULL pointer\n",where); } else { free(buf); nmembuf--; } /* calling routine took care to zero buffer if it had anything sensitive */ } /************************************************************************* * * Function: pairalloc * * Purpose: Allocate memory for VALUE_PAIR * *************************************************************************/ VALUE_PAIR * pairalloc(where) char *where; { extern int hmempair; extern int nmempair; extern int tmempair; VALUE_PAIR *pair; void rad_exit(); if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == (VALUE_PAIR *)NULL) { log_err("%s: fatal system error: out of memory, exiting\n",where); rad_exit(-1); } memset(pair,0,sizeof(VALUE_PAIR)); pair->next = (VALUE_PAIR *)NULL; nmempair++; tmempair++; if (nmempair > hmempair) { hmempair = nmempair; } return pair; } /************************************************************************* * * Function: pairfree * * Purpose: Release the memory used by a list of attribute-value * pairs. * *************************************************************************/ void pairfree(pair,where) VALUE_PAIR *pair; char *where; { extern int nmempair; VALUE_PAIR *next; while(pair != (VALUE_PAIR *)NULL) { next = pair->next; memset(pair,0,sizeof(VALUE_PAIR)); free(pair); pair = next; nmempair--; } } /************************************************************************* * * Function: peeralloc * * Purpose: Allocate memory for PEER * *************************************************************************/ PEER * peeralloc(where) char *where; { extern int hmempeer; extern int nmempeer; extern int tmempeer; PEER *peer; void rad_exit(); if((peer = (PEER *)malloc(sizeof(PEER))) == (PEER *)NULL) { log_err("%s: fatal system error: out of memory, exiting\n", where); rad_exit(-1); } memset(peer,0,sizeof(PEER)); peer->next = (PEER *)NULL; nmempeer++; tmempeer++; if (nmempeer > hmempeer) { hmempeer = nmempeer; } return peer; } /************************************************************************* * * Function: peerfree * * Purpose: Release the memory used by a PEER structure * *************************************************************************/ void peerfree(peer,where) PEER *peer; char *where; { extern int nmempeer; void reqfree(); if (peer == (PEER *)NULL) { log_err("%s called peerfree with NULL pointer\n",where); } else { if (peer->next != (PEER *)NULL) { DEBUG("%s called peerfree with live next pointer\n", where); } memset(peer,0,sizeof(PEER)); free(peer); nmempeer--; } } /************************************************************************* * * Function: reqalloc * * Purpose: Allocate memory for use by an AUTH_REQ structure * *************************************************************************/ AUTH_REQ * reqalloc(where) char *where; { extern int hmemreq; extern int nmemreq; extern int tmemreq; extern int debug_mem; AUTH_REQ *authreq; void rad_exit(); if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) == (AUTH_REQ *)NULL) { log_err("%s: fatal system error: out of memory, exiting\n",where); rad_exit(-1); } memset(authreq,0,sizeof(AUTH_REQ)); authreq->request = (VALUE_PAIR *)NULL; authreq->next = (AUTH_REQ *)NULL; authreq->packet = (char *)NULL; nmemreq++; tmemreq++; if (nmemreq > hmemreq) { hmemreq = nmemreq; } if (debug_mem) { log_err("called reqalloc(%s) = %x %d\n",where,(int)authreq,nmemreq); } return authreq; } /************************************************************************* * * Function: reqfree * * Purpose: Release the memory used by an AUTH_REQ structure * *************************************************************************/ void reqfree(authreq,where) AUTH_REQ *authreq; char *where; { extern int nmemreq; extern int debug_mem; if (debug_mem) { log_err("called reqfree(%x,%s) = %d\n",(int)authreq,where,nmemreq); } if (authreq == (AUTH_REQ *)NULL) { log_err("%s called reqfree with NULL pointer\n",where); } else { pairfree(authreq->request,where); if (authreq->packet != (char *) NULL) { buffree(authreq->packet,where); } memset(authreq, 0, sizeof(AUTH_REQ)); free(authreq); nmemreq--; } } void memreport() { extern int nmembuf,hmembuf,tmembuf, nmempair,hmempair,tmempair, nmempeer,hmempeer,tmempeer, hmemreq,nmemreq,tmemreq; log_err("memory usage = pair %d/%d/%d peer %d/%d/%d req %d/%d/%d buf %d/%d/%d\n", nmempair,hmempair,tmempair, nmempeer,hmempeer,tmempeer, nmemreq,hmemreq,tmemreq, nmembuf,hmembuf,tmembuf ); } /************************************************************************* * * Function: fprint_attr_val * * Purpose: Write a printable version of the attribute-value * pair to the supplied File. * *************************************************************************/ void fprint_attr_val(fd, pair) FILE *fd; VALUE_PAIR *pair; { DICT_VALUE *dict_valget(); DICT_VALUE *dval; char buffer[32]; char prtbuf[1060]; int len; u_char *ptr; void fprint_attr_putc(); void ipaddr2str(); switch(pair->type) { case PW_TYPE_STRING: sprintf(prtbuf, "%s = \"", pair->name); ptr = (u_char *)pair->strvalue; len = pair->lvalue; while(len-- > 0) { if(!(isprint(*ptr))) { sprintf(buffer, "\\%03o", *ptr); strcat(prtbuf, buffer); } else { fprint_attr_putc(*ptr, prtbuf); } ptr++; } fprint_attr_putc('"', prtbuf); break; case PW_TYPE_INTEGER: dval = dict_valget(pair->lvalue, pair->name); if(dval != (DICT_VALUE *)NULL) { sprintf(prtbuf, "%s = %s", pair->name, dval->name); } else { sprintf(prtbuf, "%s = %ld", pair->name, pair->lvalue); } break; case PW_TYPE_IPADDR: ipaddr2str(buffer, pair->lvalue); sprintf(prtbuf, "%s = %s", pair->name, buffer); break; case PW_TYPE_DATE: strftime(buffer, sizeof(buffer), "%b %e %Y", gmtime((time_t *)&pair->lvalue)); sprintf(prtbuf, "%s = \"%s\"", pair->name, buffer); break; default: sprintf(prtbuf, "Unknown type %d", pair->type); break; } if (fd == (FILE *)-1) { /* * send to debug log */ log_debug("%s\n", prtbuf); } else { fputs(prtbuf, fd); } } void fprint_attr_putc(cc, buf) u_char cc; u_char * buf; { int len; len = strlen((const char *)buf); buf[len] = cc; buf[len+1] = (u_char)0; } /************************************************************************* * * Function: hexdump * * Purpose: log buffer in hex * *************************************************************************/ void hexdump(buf,n) u_char *buf; int n; { int i; int j; char s[64]; if (n > 200) { n = 200; } s[48] = '\n'; s[48] = '\0'; for (i = 0; i < n; i++) { j = i & 0x0f; sprintf(&s[3*j],"%02x ",(int)buf[i]); if (j == 15) { log_debug("%s\n",s); } } if (n > 0 && j < 15) { s[3*j+3] = '\n'; s[3*j+3] = '\0'; log_debug("%s\n",s); } } radiusd-livingston-2.1/src/version.c0100644000175000017500000001024206734270175015446 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: version.c,v 1.23 1999/06/23 23:40:45 cdr Exp $ Copyright 1992-1999 Lucent Technologies Inc"; #include #include #include #include "radius.h" extern char *progname; extern int radius_dbm; extern int accept_zero; /* If you make any changes to this software please update this version number */ #define VERSION "Livingston RADIUS 2.1 1999/6/23" /************************************************************************* * * Function: version * * Purpose: Display the revision number for this program * *************************************************************************/ void version() { char buffer[1024]; void build_version(); build_version(buffer); fprintf(stderr, buffer); exit(-1); } void log_version() { char buffer[1024]; void build_version(); void log_msg(); build_version(buffer); log_msg(LOG_INFO, buffer); } void build_version(bp) char * bp; { extern int accept_zero; extern int radius_dbm; sprintf(bp, "%s: %s ", progname, VERSION); /* here are all the conditional feature flags */ # if defined(ACTIVCARD) strcat(bp," ACTIVCARD"); # endif # if defined(IPASS) strcat(bp," IPASS"); # endif # if defined(SECURID) strcat(bp," SECURID"); # endif # if defined(NDBM) strcat(bp," NDBM"); # endif #if defined(NOSHADOW) strcat(bp," NOSHADOW"); /* system has no /usr/include/shadow.h */ #endif #if defined(PASSCHANGE) strcat(bp," PASSCHANGE"); /* support deprecated radpass * for changing passwords */ #endif /* here are all the system definitions compilation uses */ #if defined(__alpha) strcat(bp," __alpha"); #endif #if defined(__FreeBSD__) strcat(bp," __FreeBSD__"); #endif #if defined(__osf__) strcat(bp," __osf__"); #endif #if defined(aix) strcat(bp," aix"); #endif #if defined(bsdi) strcat(bp," bsdi"); #endif #if defined(hpux) strcat(bp," hpux"); #endif #if defined(sun) strcat(bp," sun"); #endif #if defined(sys5) strcat(bp," sys5"); #endif #if defined(unixware) strcat(bp," unixware"); #endif #if defined(M_UNIX) strcat(bp," M_UNIX"); #endif if (accept_zero) { strcat(bp, " zero_accepted"); } strcat(bp, radius_dbm ? " dbm_users" : " flat_users"); strcat(bp,"\n"); } radiusd-livingston-2.1/src/vports.c0100644000175000017500000003466206734270175015332 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ static char sccsid[] = "$Id: vports.c,v 1.2 1999/06/23 23:40:45 cdr Exp $ Copyright 1998-1999 Lucent Technologies Inc."; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" #ifdef VPORTS #include "vports.h" extern char *radius_dir; extern void rad_exit(); int vports_init() { FILE *f1; char s[256], s2[16]; int max; int fclose(); u_char cid[16]; sprintf(s, "%s/%s", radius_dir, RADIUS_VPORTS); f1 = fopen(s, "rt"); if (f1 != NULL) { DEBUG("Found VPORTS, reading in list\n"); while(fgets(s, 256, f1) != NULL) { s[strlen(s)-1] = '\0'; /* Strip off CR */ sscanf(s, "%s %s", cid, s2); max = atoi(s2); create_cidlist(cid, max); } fclose(f1); return 1; } return 0; } VP_CALLED * begin_cidlist() { if ((cidfirst = malloc(sizeof(VP_CALLED))) == NULL) { log_err("begin_cidlist: Could not allocate memory!\n"); rad_exit(-1); } cidfirst->next = NULL; cidfirst->prev = NULL; cidlast = cidfirst; vp_cidinit = VP_LIST_INIT; return (VP_CALLED *)cidfirst; } VP_CALLED * new_cidlist() { VP_CALLED *cidcur; if (vp_cidinit != VP_LIST_INIT) { cidcur = begin_cidlist(); strcpy(cidcur->num, ""); cidcur->max = 0; cidcur->nasipinit = 0; return (VP_CALLED *)cidcur; } if ((cidcur = malloc(sizeof(VP_CALLED))) == NULL) { log_err("new_cidlist: Could not allocate memory!\n"); rad_exit(-1); } cidcur->next = NULL; cidcur->prev = cidlast; cidlast->next = cidcur; cidlast = cidcur; strcpy(cidcur->num, ""); cidcur->max = 0; cidcur->nasipinit = 0; return (VP_CALLED *)cidcur; } VP_CALLED * get_cidlist(num) u_char *num; { VP_CALLED *cidcur; cidcur = cidfirst; while(cidcur != NULL) { if (!strcmp(cidcur->num, num)) { return (VP_CALLED *)cidcur; } cidcur = cidcur->next; } return (VP_CALLED *)NULL; } void create_cidlist(num, max) u_char *num; int max; { VP_CALLED *cidcur; if ((cidcur = get_cidlist(num)) != NULL) { /* Woops! Duplicate, reset Log a warning here maybe? */ cidcur->max = max; return; } cidcur = new_cidlist(); strcpy(cidcur->num, num); cidcur->max = max; return; } int vports_in_use(cidcur) VP_CALLED *cidcur; { VP_NAS *nasip_cur; VP_ACCTID *acctid_cur; u_int ret; ret = 0; if (cidcur->nasipinit == VP_LIST_INIT) { nasip_cur = cidcur->nasip_first; while(nasip_cur != NULL) { if (nasip_cur->acctidinit == VP_LIST_INIT) { acctid_cur = nasip_cur->acctid_first; while(acctid_cur != NULL) { ret++; acctid_cur = acctid_cur->next; } } nasip_cur = nasip_cur->next; } } return ret; } int vports_in_cache(cidcur) VP_CALLED *cidcur; { VP_CALLCACHE *cc_cur; u_int ret; time_t now; time_t time(); ret = 0; time(&now); if (cidcur->callcacheinit == VP_LIST_INIT) { cc_cur = cidcur->cc_first; while(cc_cur != NULL) { if (now >= (cc_cur->tm + VP_CACHE_EXPIRE)) { free_single_cclist(cidcur, cc_cur); cc_cur = cidcur->cc_first; continue; } cc_cur = cc_cur->next; } cc_cur = cidcur->cc_first; while(cc_cur != NULL) { ret++; cc_cur = cc_cur->next; } } return ret; } VP_NAS * begin_nasiplist(cidcur) VP_CALLED *cidcur; { if ((cidcur->nasip_first = malloc(sizeof(VP_NAS))) == NULL) { log_err("begin_nasiplist: Could not allocate memory!\n"); rad_exit(-1); } cidcur->nasip_first->next = NULL; cidcur->nasip_first->prev = NULL; cidcur->nasip_first->addr = 0; cidcur->nasip_first->acctidinit = 0; cidcur->nasip_last = cidcur->nasip_first; cidcur->nasipinit = VP_LIST_INIT; return (VP_NAS *)cidcur->nasip_first; } void free_single_nasiplist(cidcur,nasip_cur) VP_CALLED *cidcur; VP_NAS *nasip_cur; { VP_NAS *next, *prev; VP_ACCTID *acctid_cur; if (nasip_cur->acctidinit == VP_LIST_INIT) { acctid_cur = nasip_cur->acctid_first; while(nasip_cur->acctid_first != NULL) { free_single_acctidlist(nasip_cur, nasip_cur->acctid_first); } nasip_cur->acctidinit = 0; } next = nasip_cur->next; prev = nasip_cur->prev; if (next != NULL) { next->prev = prev; } if (prev != NULL) { prev->next = next; } if (cidcur->nasip_first == nasip_cur) { cidcur->nasip_first = next; } if (cidcur->nasip_last == nasip_cur) { cidcur->nasip_last = prev; } free(nasip_cur); if (cidcur->nasip_first == NULL && cidcur->nasip_last == NULL) { cidcur->nasipinit = 0; } return; } VP_NAS * get_nasiplist(cidcur, addr) VP_CALLED *cidcur; UINT4 addr; { VP_NAS *nasip_cur; if (cidcur->nasipinit != VP_LIST_INIT) { return (VP_NAS *)NULL; } nasip_cur = cidcur->nasip_first; while(nasip_cur != NULL && nasip_cur->addr != addr) { nasip_cur = nasip_cur->next; } return nasip_cur; } VP_NAS * new_nasiplist(cidcur, addr) VP_CALLED *cidcur; UINT4 addr; { VP_NAS *nasip_cur; if ((nasip_cur = get_nasiplist(cidcur, addr)) != NULL) { return (VP_NAS *)nasip_cur; } if (cidcur->nasipinit != VP_LIST_INIT) { nasip_cur = begin_nasiplist(cidcur); nasip_cur->addr = addr; nasip_cur->acctidinit = 0; return (VP_NAS *)nasip_cur; } if ((nasip_cur = malloc(sizeof(VP_NAS))) == NULL) { log_err("new_nasiplist: Could not allocate memory!\n"); rad_exit(-1); } nasip_cur->next = NULL; nasip_cur->prev = cidcur->nasip_last; nasip_cur->addr = addr; nasip_cur->acctidinit = 0; if (cidcur->nasip_last != NULL) cidcur->nasip_last->next = nasip_cur; cidcur->nasip_last = nasip_cur; return (VP_NAS *)nasip_cur; } VP_CALLCACHE * begin_cclist(cidcur) VP_CALLED *cidcur; { if ((cidcur->cc_first = malloc(sizeof(VP_CALLCACHE))) == NULL) { log_err("begin_cclist: Could not allocate memory!\n"); rad_exit(-1); } cidcur->cc_first->next = NULL; cidcur->cc_first->prev = NULL; cidcur->cc_first->tm = 0; cidcur->cc_last = cidcur->cc_first; cidcur->callcacheinit = VP_LIST_INIT; return (VP_CALLCACHE *)cidcur->cc_first; } void free_single_cclist(cidcur, cc_cur) VP_CALLED *cidcur; VP_CALLCACHE *cc_cur; { VP_CALLCACHE *next, *prev; next = cc_cur->next; prev = cc_cur->prev; if (next != NULL) next->prev = prev; if (prev != NULL) prev->next = next; if (cidcur->cc_first == cc_cur) cidcur->cc_first = next; if (cidcur->cc_last == cc_cur) cidcur->cc_last = prev; free(cc_cur); if (cidcur->cc_first == NULL && cidcur->cc_last == NULL) cidcur->callcacheinit = 0; return; } VP_CALLCACHE * new_cclist(cidcur) VP_CALLED *cidcur; { VP_CALLCACHE *cc_cur; time_t time(); if (cidcur->callcacheinit != VP_LIST_INIT) { cc_cur = begin_cclist(cidcur); time(&cc_cur->tm); return (VP_CALLCACHE *)cc_cur; } if ((cc_cur = malloc(sizeof(VP_CALLCACHE))) == NULL) { log_err("new_cclist: Could not allocate memory!\n"); rad_exit(-1); } cc_cur->next = NULL; cc_cur->prev = cidcur->cc_last; time(&cc_cur->tm); if (cidcur->cc_last != NULL) cidcur->cc_last->next = cc_cur; cidcur->cc_last = cc_cur; return (VP_CALLCACHE *)cc_cur; } VP_ACCTID * begin_acctidlist(nasip_cur) VP_NAS *nasip_cur; { if ((nasip_cur->acctid_first = malloc(sizeof(VP_ACCTID))) == NULL) { log_err("begin_acctidlist: Could not allocate memory!\n"); rad_exit(-1); } nasip_cur->acctid_first->next = NULL; nasip_cur->acctid_first->prev = NULL; strcpy(nasip_cur->acctid_first->acctid, ""); nasip_cur->acctid_last = nasip_cur->acctid_first; nasip_cur->acctidinit = VP_LIST_INIT; return (VP_ACCTID *)nasip_cur->acctid_first; } void free_single_acctidlist(nasip_cur, acctid_cur) VP_NAS *nasip_cur; VP_ACCTID *acctid_cur; { VP_ACCTID *next, *prev; next = acctid_cur->next; prev = acctid_cur->prev; if (next != NULL) next->prev = prev; if (prev != NULL) prev->next = next; if (nasip_cur->acctid_first == acctid_cur) nasip_cur->acctid_first = next; if (nasip_cur->acctid_last == acctid_cur) nasip_cur->acctid_last = prev; free(acctid_cur); if (nasip_cur->acctid_first == NULL && nasip_cur->acctid_last == NULL) nasip_cur->acctidinit = 0; return; } VP_ACCTID * get_acctidlist(nasip_cur, acctid) VP_NAS *nasip_cur; u_char *acctid; { VP_ACCTID *acctid_cur; if (nasip_cur->acctidinit != VP_LIST_INIT) return (VP_ACCTID *)NULL; acctid_cur = nasip_cur->acctid_first; while(acctid_cur != NULL) { if (!strcmp(acctid_cur->acctid, acctid)) return (VP_ACCTID *)acctid_cur; acctid_cur = acctid_cur->next; } return (VP_ACCTID *)NULL; } VP_ACCTID * new_acctidlist(nasip_cur, acctid) VP_NAS *nasip_cur; u_char *acctid; { VP_ACCTID *acctid_cur; if ((acctid_cur = get_acctidlist(nasip_cur, acctid)) != NULL) { /* How did this happen???? */ return (VP_ACCTID *)acctid_cur; } if (nasip_cur->acctidinit != VP_LIST_INIT) { acctid_cur = begin_acctidlist(nasip_cur); strcpy(acctid_cur->acctid, acctid); return (VP_ACCTID *)acctid_cur; } if ((acctid_cur = malloc(sizeof(VP_ACCTID))) == NULL) { log_err("new_acctidlist: Could not allocate memory!\n"); rad_exit(-1); } acctid_cur->next = NULL; acctid_cur->prev = nasip_cur->acctid_last; strcpy(acctid_cur->acctid, acctid); if (nasip_cur->acctid_last != NULL) nasip_cur->acctid_last->next = acctid_cur; nasip_cur->acctid_last = acctid_cur; return (VP_ACCTID *)acctid_cur; } int vp_check_req(authreq) AUTH_REQ *authreq; { VALUE_PAIR *vp; VP_CALLED *cidcur; UINT4 addr; u_char called_sid[16]; int required; int in_use; int service_type; required = 0; vp = authreq->request; while(vp != NULL) { switch(vp->attribute) { case PW_USER_SERVICE_TYPE: required++; service_type = vp->lvalue; break; case PW_CLIENT_ID: required++; addr = vp->lvalue; break; case PW_CALLED: required++; strcpy(called_sid, vp->strvalue); break; } vp = vp->next; } if (required != 3) return VP_RET_IGNORE; if (service_type != PW_CALL_CHECK_USER && service_type != PW_OLD_CALL_CHECK_USER) return VP_RET_IGNORE; cidcur = get_cidlist(called_sid); if (cidcur == NULL) return VP_RET_IGNORE; in_use = vports_in_use(cidcur) + vports_in_cache(cidcur); if (in_use >= cidcur->max) { DEBUG("VPORTS: Rejecting Request, no ports available in pool %s [%d inuse, %d cached, %d max]\n", cidcur->num, vports_in_use(cidcur), vports_in_cache(cidcur), cidcur->max); return VP_RET_REJECT; } else { new_cclist(cidcur); DEBUG("VPORTS: Accepting Request to Virtual Pool %s [%d inuse, %d cached, %d max]\n", cidcur->num, vports_in_use(cidcur), vports_in_cache(cidcur), cidcur->max); return VP_RET_ACCEPT; } } void vp_update_cid(authreq) AUTH_REQ *authreq; { VALUE_PAIR *vp; VP_CALLED *cidcur; VP_NAS *nasip_cur; VP_ACCTID *acctid_cur; UINT4 addr; char *ipaddr2strp(); u_char called_sid[16]; u_char acct_id[16]; u_char reboot_req; u_char required; u_int record_type; reboot_req = 0; required = 0; vp = authreq->request; while(vp != NULL) { switch(vp->attribute) { case PW_USER_NAME: if (strcmp(vp->strvalue, "")) reboot_req++; break; case PW_CLIENT_ID: required++; addr = vp->lvalue; break; case PW_ACCT_STATUS_TYPE: required++; record_type = vp->lvalue; if (record_type == PW_STATUS_STOP) reboot_req++; break; case PW_ACCT_SESSION_ID: required++; strcpy(acct_id, vp->strvalue); break; case PW_CALLED: required++; strcpy(called_sid, vp->strvalue); break; } vp = vp->next; } if (required != 4) return; if (reboot_req == 0) { DEBUG("vports: NAS %s rebooted - clearing ports\n", ipaddr2strp(addr)); cidcur = cidfirst; while(cidcur != NULL) { nasip_cur = get_nasiplist(cidcur, addr); if (nasip_cur != NULL) { free_single_nasiplist(cidcur, nasip_cur); } cidcur = cidcur->next; } return; } cidcur = get_cidlist(called_sid); if (cidcur == NULL) { return; } switch(record_type) { case PW_STATUS_START: if (vports_in_cache(cidcur) > 0) { free_single_cclist(cidcur, cidcur->cc_first); } nasip_cur = new_nasiplist(cidcur, addr); acctid_cur = new_acctidlist(nasip_cur, acct_id); DEBUG("VPORTS: Added Session ID %s to the %s pool [%d inuse, %d cached, %d max]\n", acct_id, called_sid, vports_in_use(cidcur), vports_in_cache(cidcur), cidcur->max); break; case PW_STATUS_STOP: nasip_cur = get_nasiplist(cidcur, addr); if (nasip_cur != NULL) { acctid_cur = get_acctidlist(nasip_cur, acct_id); if (acctid_cur != NULL) { free_single_acctidlist(nasip_cur, acctid_cur); DEBUG("VPORTS: Removed Session ID %s from the %s pool [%d inuse, %d cached, %d max]\n", acct_id, called_sid, vports_in_use(cidcur), vports_in_cache(cidcur), cidcur->max); } } break; default: break; } return; } #endif /* VPORTS */ radiusd-livingston-2.1/src/vports.h0100644000175000017500000000754206734270175015334 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ /* * $Id: vports.h,v 1.2 1999/06/23 23:40:45 cdr Exp $ Copyright 1998 Lucent Technologies, Inc. */ #ifdef VPORTS #define VP_LIST_INIT 0xff #define VP_RET_IGNORE 0 #define VP_RET_REJECT 1 #define VP_RET_ACCEPT 2 #define VP_CACHE_EXPIRE 30 /* in seconds */ typedef struct vp_callcache { time_t tm; struct vp_callcache *next; struct vp_callcache *prev; } VP_CALLCACHE; typedef struct vp_acctid { char acctid[32]; struct vp_acctid *next; struct vp_acctid *prev; } VP_ACCTID; typedef struct vp_nas { UINT4 addr; u_char acctidinit; VP_ACCTID *acctid_first; VP_ACCTID *acctid_last; struct vp_nas *next; struct vp_nas *prev; } VP_NAS; typedef struct vp_called { char num[16]; u_int max; u_char nasipinit; u_char callcacheinit; VP_NAS *nasip_first; VP_NAS *nasip_last; VP_CALLCACHE *cc_first; VP_CALLCACHE *cc_last; struct vp_called *next; struct vp_called *prev; } VP_CALLED; int vports_init(); VP_CALLED *begin_cidlist(); VP_CALLED *new_cidlist(); VP_CALLED *get_cidlist(u_char *num); void create_cidlist(u_char *num, int max); int vports_in_use(VP_CALLED *cidcur); int vports_in_cache(VP_CALLED *cidcur); VP_CALLCACHE *begin_cclist(VP_CALLED *cidcur); void free_single_cclist(VP_CALLED *cidcur, VP_CALLCACHE *cc_cur); VP_CALLCACHE *new_cclist(VP_CALLED *cidcur); VP_NAS *begin_nasiplist(VP_CALLED *cidcur); void free_single_nasiplist(VP_CALLED *cidcur, VP_NAS *nasip_cur); VP_NAS *get_nasiplist(VP_CALLED *cidcur, UINT4 addr); VP_NAS *new_nasiplist(VP_CALLED *cidcur, UINT4 addr); VP_ACCTID *begin_acctidlist(VP_NAS *nasip_cur); void free_single_acctidlist(VP_NAS *nasip_cur, VP_ACCTID *acctid_cur); VP_ACCTID *get_acctidlist(VP_NAS *nasip_cur, u_char *acctid); VP_ACCTID *new_acctidlist(VP_NAS *nasip_cur, u_char *acctid); int vp_check_req(AUTH_REQ *authreq); void vp_update_cid(AUTH_REQ *authreq); VP_CALLED *cidfirst; VP_CALLED *cidlast; u_char vp_cidinit; #endif /* VPORTS */ radiusd-livingston-2.1/LICENSE0100644000175000017500000000375506734304671014045 0ustar pmpm/*********************************************************************** RADIUS Remote Authentication Dial In User Service Lucent Technologies Remote Access 4464 Willow Road Pleasanton, CA 94588 Copyright 1992-1999 Lucent Technologies Inc. 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. * All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Lucent Technologies and its contributors. * Neither the name of the copyright holder nor the names of its 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 holder 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. ************************************************************************/ radiusd-livingston-2.1/README0100644000175000017500000006376406734304671013726 0ustar pmpm1999/6/23 RADIUS Server 2.1 Release Note The Lucent Remote Access RADIUS server 2.1 with support for RADIUS proxy, iPass roaming, and ActivCard is now available in binary form for the following platforms, and in source form. IBM RS6000 AIX 4.2 Alpha Digital UNIX 4.0 BSD/OS 3.0 HP-UX 10.20 Slackware Linux 2.0 Redhat Linux 5.2 SGI IRIX 6.3 SunOS 4.1.4 Solaris 2.5.1 Solaris x86 2.5.1 NOTE! This release removes the obsolete RADPASS feature. In addition, User-Name values with embedded "at" signs (@) are now treated as proxy realms. RADIUS server 2.1 includes a new dictionary file with support for the Class, LE-Advice-of-Charge, and LE-Terminate-Detail attributes added in ComOS(R) 3.8. Attributes added in ComOS 3.9 and 4.1 are also included. The sradiusd daemon provides support for ActivCard on platforms supported by ActivEngine 2.1: AIX, HP-UX, SunOS, and Solaris. All other files are the same as in RADIUS server 2.0.1. Support is available only for customers owning Lucent PortMaster products. Information on contacting Lucent Remote Access technical support is listed at the end of this release note. The radiusd daemon uses GDBM 1.7.3 instead of NDBM on some systems; the source for GDBM is available for free from ftp://ftp.gnu.org/pub/gnu/gdbm/ and other Free Software Foundation (FSF) distribution sites. _______________ Contents RADIUS Server Features Y2K compliant Proxy RADIUS ActivCard iPass Support Accounting Signatures Now Required Vendor-Specific Attributes Virtual Ports Alternate Password File Address Binding Improved Messages Enhanced Debugging Bugs Fixed RADIUS test program radtest How Proxy RADIUS Works and How to Configure It Upgrading Support _______________ RADIUS Server Features RADIUS server 2.1 supports the following features: Y2K Compliance RADIUS server 2.1 is Y2K compliant. It treats all dates internally as 32-bit unsigned integers or time_t, and prints years in 4-digit format (for example, 1999). You must ensure that the operating system you are running the RADIUS server on is also Y2K compliant. All PortMaster products are Y2K compliant because they do not track the year. Proxy RADIUS Proxy RADIUS is a feature in which one RADIUS server can forward an authentication request to a remote RADIUS server, and return its reply to the network access server (NAS). A common use for proxy RADIUS is roaming. Roaming permits two or more ISPs to allow each other's users to dial in to either ISP's network for service. For more information on proxy RADIUS, see "How Proxy RADIUS Works and How to Configure It" later in this release note. ActivCard RADIUS server 2.1 now supports ActivCard as well as SecurID for authentication. Do the following to authenticate a user with ActivCard: 1. Install the new ActivCard server on the same host as the RADIUS server or another host. 2. Create the /etc/raddb/config.aeg file on your RADIUS server host describing the parameters used to connect to the ActivCard server. 3. Use "Auth-Type = ActivCard" as a check item for the user. iPass Support RADIUS server 2.1 now supports the iPass protocol. Do the following to use iPass: 1. Register at the iPass website http://www.ipass.com/. 2. Add the "ipass" keyword to the appropriate entries in your /etc/raddb/proxy file. 3. Run the iradiusd binary instead of radiusd. Direct any problems with the iPass support to iPass technical support first; iPass will contact Lucent Remote Access, if necessary. Accounting Signatures Now Required Earlier releases of the Lucent Remote Access RADIUS server logged RADIUS accounting packets even if their request authenticators were invalid. This behavior provided backwards compatibility with ComOS 3.3 and earlier releases. RADIUS server 2.1 now discards invalid accounting packets and logs an error message. CAUTION! If you have any PortMaster running ComOS 3.3 or earlier, you must upgrade it to ComOS release 3.3.1 or later to use RADIUS server 2.1. The -o flag is provided for backwards compatibility with noncompliant RADIUS clients. If radiusd is run with the -o flag, it logs unsigned accounting records, and flags them with "Request-Authenticator = None". If radiusd is run without the -o flag, it does not log unsigned accounting records. Vendor-Specific Attributes RADIUS server 2.1 supports vendor-specific attributes in accounting-request packets to support the LE-Advice-of-Charge and LE-Terminate-Detail attributes added in ComOS 3.8. ComOS releases are available at http://www.livingston.com/forms/one-click-dnload.cgi and via FTP at ftp://ftp.livingston.com/pub/le/upgrades/. The dictionary file uses the following syntax to define vendor-specific attributes that follow the suggested format in RFC 2138: # # Vendor-Specific attributes use the SMI Network Management Private # Enterprise Code from the "Assigned Numbers" RFC. # VENDOR Livingston 307 # Livingston Vendor-Specific Attributes (requires ComOS 3.8 and RADIUS 2.1) ATTRIBUTE LE-Terminate-Detail 2 string Livingston ATTRIBUTE LE-Advice-of-Charge 3 string Livingston LE-Terminate-Detail is a string, included in RADIUS Accounting Stop records generated by ComOS 3.8, that contains a detailed description of the reason for session termination. LE-Advice-of-Charge is a string containing the Advice of Charge information (if any) provided on the ISDN D channel by the telephone company. Virtual Ports If the file /etc/raddb/vports exists, it restricts the number of logins to each telephone number listed in the file. The first column of the file contains the Called-Station-Id, and the second column contains the number of logins permitted into that telephone number. This "virtual ports" feature provides only an approximate access control. Logins occurring before radiusd starts running are not considered in the count, nor are accounting records that go to the backup accounting server. To use this feature you must run radiusd with the -s (single-threaded) flag, and your must run the authentication and accounting servers on the same host. This feature does not provide simultaneous login limits for users. It is based on Called-Station-Id, not Calling-Station-Id. Alternate Password File You can use the -f flag with radiusd to specify an alternative to the password file /etc/passwd. Address Binding The -i
flag to radiusd instructs the RADIUS server to bind to the specified IP address to listen for requests, instead of binding to any address. This address binding is useful for running radiusd on multihomed hosts. Improved Messages * The Calling-Station-Id, where known, is now included in the syslog message for many kinds of rejected access-requests, to help you identify where failed login attempts are dialing from. Currently, this value is logged to syslog for unknown users and for failed "Auth-Type = System" logins. For example: Jul 10 21:10:50 ra radius[14870]: unix_pass: password for "bob" at 5551234 failed The actual syslog message appears on one line, but is broken into two lines here for legibility. * Other log messages are now more detailed. For example: Jul 10 21:10:50 ra radius[14870]: forwarding request from 192.168.96.6/1093.139 to 172.16.3.24/1645.17 for edu.com The numbers after the slash are the UDP port (1645) and the RADIUS message ID (17) for easier tracking. The actual syslog message appears on one line, but is broken into two lines here for legibility. Enhanced Debugging Sending a SIGUSR1 signal to radiusd now turns on debugging, and sending SIGUSR2 turns off debugging. Either signal, or exiting radiusd, logs a short summary of the daemon's activity. The format is subject to change, but for this release the summary looks like the following examples. The actual syslog message appears on one line, but is broken into two lines here for legibility. Example 1 Mar 19 23:10:50 ra radius[14870]: counters 5 8 / 2 4 / accept 4 reject 1 challenge 0 response 8 In this example, five packets were received on the RADIUS port (usually 1645 unless changed with the -p flag), eight packets were received on the RADIUS accounting port. Two RADIUS proxy replies were received, and four RADIUS accounting proxy replies were received. The RADIUS server sent four access-accepts, one access-reject, no access-challenges, and eight accounting responses. Example 2 Jul 28 09:56:01 ra radius[19340]: memory usage = pair 8/35/4784 peer 0/0/0 req 1/4/570 buf 1/4/570 This memory usage summary displays allocations for each of the four major data structures used by radiusd, in the format x/y/z: * x is the number of data structures allocated but not yet freed. * y is the high-water mark (the most structures ever allocated but not freed at one time). * z is the total number of structures allocated. _______________ Bugs Fixed * A misconfigured user entry that has a check item of Auth-Type = Local with no Password check item now rejects the user with the debug message "Warning: entry for user is missing its Password check item". * An unknown Auth-Type check item now generates an error message and rejects the user. * A memory leak that resulted from the use of multiple DEFAULT user entries is fixed. * The password decryption code no longer calculates the next RSA Data Security, Inc. MD5 Message-Digest Algorithm (MD5) digest when it does not need to. * The radiusd daemon is now strictly compliant with RFC 2139 and discards accounting-request packets with invalid request authenticators. As a result, you must run ComOS 3.3.1 or later to use RADIUS accounting with RADIUS server 2.1. The -o flag is provided for backwards compatibility with noncompliant RADIUS clients. * Assorted memory leaks and pointer problems have been corrected. _______________ RADIUS test program radtest RADIUS 2.1 includes a simple example client program called radtest, that sends a RADIUS packet to a server running on the same host as radtest, and prints out the attributes returned. It doesn't support accounting packets yet. It always fills in the NAS-IP-Address as 127.0.0.1 and the NAS-Port as 1. Passwords longer than 16 characters are not supported. It looks for its dictionary in the same directory it is run from. radtest -v prints the version. radtest -h prints help: ./radtest -d called_id -f -g calling_id -h -i id -p port -s secret -t type -v -x -u username password The other flags work as follows: -d Called Station Id -f Send framed dialin hint -g Calling Station Id -i Use id as the packet identifier -p Use port as the port (defaults to definition in /etc/services, or 1645) -s to specify shared secret (defaults to "localkey") -t send type as service type (overrides -f) -u Specifies username and password (notice that this takes two arguments) -x debug option (doesn't do anything currently) _______________ How Proxy RADIUS Works and How to Configure It Proxy RADIUS is a feature in which one RADIUS server can forward an authentication request to a remote RADIUS server, and return its reply to the NAS. A common use for proxy RADIUS is "roaming." Roaming permits two or more ISPs to allow each other's users to dial in to either ISP's network for service. The "network access server (NAS)" (PortMaster) sends its RADIUS access-request to the "forwarding server," which forwards it to the "remote server." The remote server sends an access-accept, access-reject, or access-challenge resonse back to the forwarding server, which sends it back to the NAS. The choice of which server to forward the request to is based on the authentication "realm." Realms A realm can be either of the following: * The part following the "at" sign (@) in a username (a "named realm") * A Called-Station-Id (a "numbered realm") The forwarding server checks for a numbered realm before checking for a named realm. Frequently, a domain name is used as the named realm to provide uniqueness. The RADIUS server 2.1 radiusd daemon also supports the "realm/user" style of username, but Lucent Remote Access recommends that you avoid this username style. Support is provided for older RADIUS servers that require it. However, because the "at" sign (@) always takes precedence over the slash (/), radiusd interprets the username "a/b@c" as user "a/b" in the named realm "c", for example. Such mixtures are strongly discouraged and might not be supported in future releases. Accounting Information RADIUS accounting-request packets are logged by both the forwarding server and remote server, but are acknowledged to the NAS only when the remote server sends an accounting-response back to the forwarding server. NOTE! The remote server places the accounting information in a directory under /usr/adm/radacct named after the forwarding server, NOT the NAS. Required Versions of RADIUS Both the forwarding server and remote server must be running this release of the Lucent Remote Access RADIUS server, or a current version of Lucent PortAuthority(tm). Any other vendor's conforming RADIUS proxy server is likely to work as either the forwarding server or remote server if that vendor has implemented proxy correctly. Lucent Remote Access RADIUS server versions 2.0.1 and earlier do not support proxy RADIUS, but can still be used as a remote server through the use of the "old" flag in the proxy file on the forwarding server. Port Numbers Used This RADIUS server listens on UDP port 1645 for access-requests and on UDP port 1646 for accounting-requests. It sends proxy requests from UDP ports 1650 and 1651 and listens for proxy responses on those ports. If the listening port is set with the -p flag to radiusd, then radiusd does the following: * Listens on the specified UDP port for access-requests * Listens on the port numbered 1 higher for accounting-requests * Uses ports numbered 5 higher and 6 higher to send proxy requests For example, if you run "radiusd -p 1812", then radiusd uses UDP ports 1812, 1813, 1817 and 1818. Versatility The forwarding and remote RADIUS servers can run on different operating systems. A RADIUS server can function as both a forwarding server and a remote server, serving as a forwarding server for some realms and a remote server for other realms. Use care to avoid forwarding loops -- a packet passed back and forth between two misconfigured forwarding servers. One forwarding server can forward to any number of remote servers (one per realm). A remote server can have any number of servers forwarding to it and can provide authentication for any number of realms. Proxy Scenario The following scenario illustrates the communication between a PortMaster and the forwarding and remote RADIUS servers: 1. A PortMaster sends its access-request to the forwarding server. 2. The forwarding server forwards the access-request to the remote server. 3. The remote server sends an access-accept, access-reject, or access-challenge back to the forwarding server. For this example, an access-accept is sent. 4. The forwarding server sends the access-accept to the PortMaster. 5. The PortMaster sends an accounting-request to the forwarding server. 6. The forwarding server logs the accounting-request and forwards it to the remote server. 7. The remote server logs the accounting-request and sends an accounting-response to the forwarding server. 8. The forwarding server sends the accounting-response to the PortMaster. To set up proxy, create a proxy file in the /etc/raddb directory on the forwarding server. If named realms are used, a proxy file must also exist on the remote server. If only numbered realms are used, the remote server does not need a proxy file. To use proxy, you set up RADIUS as you do normally. In addition, to form the communication between the forwarding and remote servers, you must define the following information in the clients and proxy files in /etc/raddb: On the forwarding server: o The clients file must have an entry for the PortMaster hostname or IP address and its shared secret. o The proxy file must have an entry for the remote RADIUS server's hostname or IP address, its shared secret, and its realm. The shared secret in the forwarding server's proxy file must match the shared secret in the remote server's clients file. On the remote server: o The clients file must contain the forwarding server's hostname or IP address and its shared secret. The shared secret must match the shared secret in the forwarding server's proxy file. o If any named realms are used, the proxy file must contain the hostname or IP address of the remote server itself, an unused shared secret, and the realm this remote server is authoritative for. If only numbered realms are used, then no proxy file needs to be defined on the remote server. Proxy File Example The /etc/raddb/proxy file contains proxy server hostnames (or IP addresses), shared secrets, and realms, all separated by spaces or tabs. Each line describes one realm. Here is a proxy file example: radius.edu.net secretupto16char edu.net s134.net.com someothersec2ret 5551134 net54.edu.net bettersecretthan 5555454 rad.edu.com chsebetterth edu.com 1645 rad7.com.net lx4zDFapa3ep com.net 1645 1646 old radius.edu.net eajsdfljasep 5551234 1812 1813 secure eg.edu.net e997asepdflj edu.net old secure o The first field is a valid hostname or IP address. o The second field (separated by blanks or tabs) is the shared secret. o The third field is the named or numeric authentication realm. o The remaining fields can be empty, or can contain the RADIUS port number of the remote server, the RADIUS accounting port number of the remote server, and any of the following optional keywords: old Strips the realm from the username and does not attach Proxy-State when forwarding. This keyword is useful for forwarding requests to older RADIUS servers. secure Allows the remote server to authorize administrative logins for your client. If this keyword is not present, access-accepts from the forwarding server that grant Administrative or NAS-Prompt access are treated as access-rejects instead. If you use this keyword, you are allowing the remote server to let someone log in to your NAS as an administrator, so use it with caution! ipass Uses the iPass protocol (instead of RADIUS) to communicate with the remote server. See http:/www.ipass.com/ for more information. The optional fields can be specified in any order, separated by blanks or tabs, after the first three mandatory fields. If you specify a single UDP port, it is used for the RADIUS port. If you specify two ports, they are used as the RADIUS port and RADIUS accounting port in that order. If you specify no ports, they default to the same ports used by the RADIUS server itself. If "secure" is not specified for a remote server and it replies with Service-Type = Administrative-User or NAS-Prompt-User, the forwarding server treats it as an access-reject and logs the following message to syslog: Jul 10 21:10:00 ra radius[14870]: remote server 192.168.96.6/1645.4 returned insecure service for client 172.16.3.24/1039.17, sending reject instead If the hostname (or IP address) listed in the proxy file is the same as the primary hostname or IP address of the host running the RADIUS server, and the UDP port in the entry matches the UDP port the message was received on, radiusd determines that the user is local, strips off the "@domain" portion, and processes the request locally. Special Named Realms The special named realm "DEFAULT" (all uppercase) matches any named realm not found in the proxy file. If more than one DEFAULT entry exists in the proxy file, only the last one is used. For example: center.com.net e199aespfdx4 DEFAULT The special named realm "NOREALM" (all uppercase) matches any user that has no realm. If more than one NOREALM entry exists in the proxy file, only the last one is used. For example: others.com.net e19aepsfd9x4 NOREALM Example Configuration for Proxy RADIUS The following example illustrates a typical proxy RADIUS topology and the sample configuration of proxy and clients files. Equipment: o PortMaster named "pmtest" with IP address 192.168.10.1 o Forwarding server named "forward" with an IP address of 192.168.10.2 o Remote server named "remote" with an IP address of 172.16.25.5 In a real configuration, you must use IP addresses or fully qualified domain names as hostnames. 1. Configure the contents of clients and proxy files of the server called "forward" as follows: /etc/raddb/clients ------------------ pmtest sharedsecret /etc/raddb/proxy ---------------- remote testsecret com.net 2. Configure the contents of clients and proxy files of the server called "remote" as follows: /etc/raddb/clients ------------------ forward testsecret /etc/raddb/proxy ---------------- remote doesntmatter com.net 3. On the PortMaster "pmtest", enter the following commands to set the authentication and accounting servers: set authentic 192.168.10.2 set secret sharedsecret set accounting 192.168.10.2 save all 4. For a user to be authenticated via the remote server, define a profile for this user in the users file of the remote server. A user profile is defined in the following format. Note that the remote server strips the named realm from the username before looking it up in the users file. test Password = "testing" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-Routing = None Alternatively, if the test user's password is stored in the /etc/passwd file, the example user profile is the following: test Auth-Type = System Service-Type = Framed-User, Framed-Protocol = PPP, Framed-IP-Address = 255.255.255.254, Framed-Routing = None 5. Run the radiusd daemon on both "forward" and "remote" servers. The RADIUS accounting records are logged in the detail file of each server. A user dialing in to the PortMaster must enter "test@com.net" at the login prompt and a password at the password prompt. Limitation of Proxy For the RADIUS server to handle numbered realms for points of presence (POPs) from multiple area codes, the RADIUS server must be configured with the area code of each PortMaster if that information is not included in the Called-Station-Id. The ability to determine the area code is not included in RADIUS server 2.1. This limitation is a problem only if your situation includes ALL of the following: * You use the same 7-digit telephone number in multiple area codes to belong to different realms. * You use the same RADIUS forwarding server for all area codes and/or all realms. * Your telephone company does not include the area code in the Calling-Station-Id. _______________ Upgrading RADIUS server 2.1 is available in source form at ftp://ftp.livingston.com/pub/le/radius/radius21.tar.Z and in binary form for the following platforms at ftp://ftp.livingston.com/pub/le/software/: IBM RS6000 AIX 4.2 aix/radius21.tar.Z Alpha Digital UNIX 4.0 alpha/radius21.tar.Z BSD/OS 3.0 bsdi/radius21.tar.Z HP/UX 10.20 hp/radius21.tar.Z Slackware Linux 2.0 linux/radslack21.tar.Z Redhat Linux 5.2 linux/radhat21.tar.Z SGI IRIX 6.3 sgi/radius21.tar.Z SunOS 4.1.4 sun4/radsun21.tar.Z Solaris 2.5.1 sun4/radsol21.tar.Z Solaris x86 2.5.1 sun86/radius21.tar.Z For other flavors of UNIX, including Linux, FreeBSD, NetBSD, and BSD/OS 4.0, get the source and compile from that. RADIUS 2.1 is not available for Windows NT. To upgrade, do the following: 1. Save a copy of your old dictionary file and radiusd daemon. 2. Copy the new dictionary file to /etc/raddb or whatever directory you use. 3. If you are using proxy, create a /etc/raddb/proxy file. 4. Kill your existing radiusd, and run the new radiusd. - If you are using SecurID or ActivCard for authentication, run sradiusd instead of radiusd. - If you are using iPass, run iradiusd instead of radiusd. - If you are running iPass AND SecurID or ActivCard, modify the Makefile to link all the appropriate libraries. Contact support@livingston.com if you need assistance in doing so. _________________________________________________________________ Copyright and Trademarks Copyright 1999 Lucent Technologies. All rights reserved. PortMaster, ComOS, and ChoiceNet are registered trademarks of Lucent Technologies Inc. PMVision, IRX, and PortAuthority are trademarks of Lucent Technologies Inc. PolicyFlow is a service mark of Lucent Technologies Inc. All other marks are the property of their respective owners. Notices Lucent Technologies Inc. makes no representations or warranties with respect to the contents or use of this publication, and specifically disclaims any express or implied warranties of merchantability or fitness for any particular purpose. Further, Lucent Technologies, Inc. reserves the right to revise this publication and to make changes to its content, any time, without obligation to notify any person or entity of such revisions or changes. Contacting Lucent Remote Access Technical Support Lucent Technologies Remote Access Business Unit (previously Livingston Enterprises) provides technical support via voice, electronic mail, or through the World Wide Web at http://www.livingston.com/. Please include the output of radiusd -v and uname -a when reporting problems with this release. Internet service providers (ISPs) and other end users in Europe, the Middle East, Africa, India, and Pakistan should contact their authorized Lucent Remote Access sales channel partner for technical support; see http://www.livingston.com/International/EMEA/distributors.html. For North and South America and Asia Pacific customers, technical support is available Monday through Friday from 7 a.m. to 5 p.m. U.S. Pacific Time (GMT -8). Dial 1-800-458-9966 within the United States (including Alaska and Hawaii), Canada, and the Caribbean and Latin America (CALA), or 1-925-737-2100 from elsewhere, for voice support. For email support send to support@livingston.com (asia-support@livingston.com for Asia Pacific customers).