/* * Copyright (C) 1997-2000 SpellCaster Telecommunications Inc. * $Id: radius.h,v 1.5 2004/10/20 05:09:54 bcrl Exp $ * Released under the GNU Public License. See LICENSE file for details. */ #ifndef RADIUS_CC #define RADIUS_CC #include "queue.h" #include "timer.h" #include "usca.h" #ifndef SELECTOPS_H #include "selectops.h" #endif #include "md5.h" #include #define RAD_MAX_PKT_SIZE 2048 enum Radius_Codes { RC_ACCESS_REQUEST = 1, RC_ACCESS_ACCEPT, RC_ACCESS_REJECT, RC_ACCOUNTING_REQUEST, RC_ACCOUNTING_RESPONSE, RC_ACCESS_CHALLENGE = 11, RC_STATUS_SERVER, RC_STATUS_CLIENT }; enum Radius_Types { RT_USER_NAME = 1, RT_USER_PASSWORD, RT_CHAP_PASSWORD, RT_NAS_IP_ADDRESS, RT_NAS_PORT, RT_SERVICE_TYPE, RT_FRAMED_PROTOCOL, RT_FRAMED_IP_ADDRESS, RT_FRAMED_IP_NETMASK, RT_FRAMED_ROUTING, RT_FILTER_ID, RT_FRAMED_MTU, RT_FRAMED_COMPRESSION, RT_LOGIN_IP_HOST, RT_LOGIN_SERVICE, RT_LOGIN_TCP_PORT, RT_unassigned1, RT_REPLY_MESSAGE, RT_CALLBACK_NUMBER, RT_CALLBACK_ID, RT_unassigned2, RT_FRAMED_ROUTE, RT_FRAMED_IPX_NETWORK, RT_STATE, RT_CLASS, RT_VENDOR_SPECIFIC, RT_SESSION_TIMEOUT, RT_IDLE_TIMEOUT, RT_TERMINATION_ACTION, RT_CALLED_STATION_ID, RT_CALLING_STATION_ID, RT_NAS_IDENTIFIER, RT_PROXY_STATE, RT_LOGIN_LAT_SERVICE, RT_LOGIN_LAT_NODE, RT_LOGIN_LAT_GROUP, RT_FRAMED_APPLETALK_LINK, RT_FRAMED_APPLETALK_NETWORK, RT_FRAMED_APPLETALK_ZONE, RT_ACCT_STATUS_TYPE = 40, RT_ACCT_DELAY_TIME, RT_ACCT_INPUT_OCTETS, RT_ACCT_OUTPUT_OCTETS, RT_ACCT_SESSION_ID, RT_ACCT_AUTHENTIC, RT_ACCT_SESSION_TIME, RT_ACCT_INPUT_PACKETS, RT_ACCT_OUTPUT_PACKETS, RT_ACCT_TERMINATE_CAUSE, RT_ACCT_MULTI_SESSION_ID, RT_ACCT_LINK_COUNT, RT_ACCT_INPUT_GIGAWORDS, RT_ACCT_OUTPUT_GIGAWORDS, RT_CHAP_CHALLENGE = 60, RT_NAS_PORT_TYPE, RT_PORT_LIMIT, RT_LOGIN_LAT_PORT, /* From RFC 3162 */ RT_NAS_IPV6_ADDRESS = 95, RT_FRAMED_INTERFACE_ID, RT_FRAMED_IPV6_PREFIX, RT_LOGIN_IPV6_HOST, RT_FRAMED_IPV6_ROUTE, RT_FRAMED_IPV6_POOL, }; class RadiusClient; class RadiusStatusReq; class RadiusReq : public CTimer, public CQueueItem, OptionReq_t { public: RadiusClient *m_client; CfgMessage_t m_cfg; u8 m_authenticator[16]; u8 m_ident; u8 m_cfg_done; u8 m_retrans_count; u8 m_have_ident; unsigned m_have_message_authenticator_tail : 1, m_calc_simple_authenticator : 1; u8 pad[3]; MD5_CTX m_md5; virtual void TimerExpired(void); public: CuscArray m_pkt; RadiusReq(void); ~RadiusReq(void); void Go_cfg(void (*cbf)(void *, OptionSet_t *), void *obj, OptionSet_t *options); void Go(AcctMessage_t *); int HaveIdent(void) { return m_have_ident; } void SetIdent(u8 ident); int decodeAscendDataFilter(u8 *data, int length, OptionSet_t *options); int decodeAscendRadiusRsp(u8 *data, int length, OptionSet_t *options); int decodeBayNetworksRadiusRsp(u8 *data, int length, OptionSet_t *options); int decodeERXRadiusRsp(u8 *data, int length, OptionSet_t *options); int decodeLucentRadiusRsp(u8 *data, int length, OptionSet_t *options); int decodeVendorRadiusRsp(u8 *data, int length, OptionSet_t *options); void RadiusRsp(CuscArray *); virtual void RadiusCallback(OptionSet_t *options); void CancelGetConfig(void); virtual void RadiusParseRsp(CuscArray *, u8 code); //friend RadiusClient::Transmit(RadiusReq &); void decodeFramedIpv6Route(OptionSet_t *options, char *data, int length); }; class RadiusClient : CTimer, public SelectEventHandler { private: #define RADIUSCLIENT_N_REQS 256 RadiusReq *m_reqs[RADIUSCLIENT_N_REQS]; /* one request per identifier */ int m_sockfd; u8 *m_secret; /* secret used for encrypting passwords */ int m_secret_len; public: u8 m_init_failed; private: u8 m_have_local_sin; u8 m_next_ident; u8 m_up; CQueue m_queue; struct sockaddr_in m_sin; struct sockaddr_in m_local_sin; unsigned long m_keepalive_interval; public: RadiusClient *m_next; RadiusClient(struct sockaddr_in server, unsigned long keepalive, struct sockaddr_in *loc_sin, ctrlfd_t *cfd); ~RadiusClient(); #if 0 void newReq(CfgMessage_t &cfgreq) { RadiusReq *req = new RadiusReq(cfgreq); /* find a free identifier */ u8 orig = m_ident++; while (m_reqs[m_ident] && m_ident != orig) ; req->SetIdent(m_ident); } #endif void RemoveReq(RadiusReq *req, u8 ident) { if (m_reqs[ident] == req) m_reqs[ident] = NULL; else m_queue.Remove(req); } void Retrans(RadiusReq *req); void QueueReq(RadiusReq *req); virtual void SelectEvent(int fd, SelectEventType event); friend void bradius_show_running_config(ctrlfd_t *cfd, int verbose); int is_sin(struct sockaddr_in *sin) { if ((m_sin.sin_family == sin->sin_family) && (m_sin.sin_addr.s_addr == sin->sin_addr.s_addr) && (m_sin.sin_port == sin->sin_port)) return 1; return 0; } int is_local_sin(struct sockaddr_in *sin) { if (!sin && !m_have_local_sin) return 1; if (!sin) return 0; if (!m_have_local_sin) return 0; if ((m_local_sin.sin_family == sin->sin_family) && (m_local_sin.sin_addr.s_addr == sin->sin_addr.s_addr) && (m_local_sin.sin_port == sin->sin_port)) return 1; return 0; } const char *get_ip(void) { return iptostr(ntohl(m_sin.sin_addr.s_addr)); } void mark_Up(void) { m_up = 1; } void mark_Down(void) { m_up = 0; } int is_Up(void) { return m_up; } /* timer expiry used for keepalive */ virtual void TimerExpired(void); }; class RadiusStatusReq : RadiusReq { private: ctrlfd_t *m_cfd; public: RadiusStatusReq(ctrlfd_t *cfd); virtual void RadiusParseRsp(CuscArray *, u8 code); virtual void RadiusCallback(OptionSet_t *options); void Go_status(RadiusClient *client); }; extern void setup_radius(ctrlfd_t *cfd, const char *ip, int acct); extern void bradius_show_running_config(ctrlfd_t *cfd, int verbose); /* username maping */ struct user_map { struct user_map *next; char *old_user; char *new_user; }; struct user_map *user_map_lookup(const char *old); #endif