📄 diameter_nasreq_server_fsm.cxx
字号:
/* BEGIN_COPYRIGHT *//* *//* Open Diameter: Open-source software for the Diameter and *//* Diameter related protocols *//* *//* Copyright (C) 2002-2004 Open Diameter Project *//* *//* This library is free software; you can redistribute it and/or modify *//* it under the terms of the GNU Lesser General Public License as *//* published by the Free Software Foundation; either version 2.1 of the *//* License, or (at your option) any later version. *//* *//* This library is distributed in the hope that it will be useful, *//* but WITHOUT ANY WARRANTY; without even the implied warranty of *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *//* Lesser General Public License for more details. *//* *//* You should have received a copy of the GNU Lesser General Public *//* License along with this library; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *//* USA. *//* *//* In addition, when you copy and redistribute some or the entire part of *//* the source code of this software with or without modification, you *//* MUST include this copyright notice in each copy. *//* *//* If you make any changes that are appeared to be useful, please send *//* sources that include the changed part to *//* diameter-developers@lists.sourceforge.net so that we can reflect your *//* changes to one unified version of this software. *//* *//* END_COPYRIGHT */// $Id: diameter_nasreq_server_fsm.cxx,v 1.7 2004/08/16 16:17:26 vfajardo Exp $// diameter_nasreq_server_fsm.cxx: NASREQ session handling// Written by Yoshihiro Ohba// Created May 3, 2004#include <ace/Singleton.h>#include <ace/Atomic_Op_T.h>#include "diameter_nasreq_server_session.hxx"#include "diameter_nasreq_server_fsm.hxx"#include "diameter_nasreq_parser.hxx"#include "diameter_nasreq_authinfo.hxx"class DiameterNasreqServerAction : public AAA_Action<DiameterNasreqServerStateMachine>{ virtual void operator()(DiameterNasreqServerStateMachine&)=0; protected: DiameterNasreqServerAction() {} ~DiameterNasreqServerAction() {}};/// State table used by DiameterEapServerStateMachine.class DiameterNasreqServerStateTable_S : public AAA_StateTable<DiameterNasreqServerStateMachine>{ friend class ACE_Singleton<DiameterNasreqServerStateTable_S, ACE_Recursive_Thread_Mutex>; private: class AcForwardAuthInfo : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AAA_LOG(LM_DEBUG, "[%N] forwarding authinfo to application.\n"); sm.ForwardAuthenticationInfo(sm.AuthenticationInfo()); } }; class AcCheckAA_Request : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AAA_LOG(LM_DEBUG, "[%N] Copying AA-Request to AA-Answer.\n"); if (sm.CheckAA_Request()) sm.Event(DiameterNasreqServerStateMachine::EvSgValidAA_Request); else sm.Event(DiameterNasreqServerStateMachine::EvSgInvalidAA_Request); } }; class AcSendAA_AnswerWithContinue : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AAA_LOG(LM_DEBUG, "[%N] Sending AA-Answer with AAA_MULTI_ROUND_AUTH.\n"); // Set Result-Code to AAA_MULTI_ROUND_AUTH. AA_AnswerData& aaAnswer = sm.AA_Answer(); aaAnswer.ResultCode = AAA_MULTI_ROUND_AUTH; // Set reply message if needed. aaAnswer.ReplyMessage.Clear(); sm.SetReplyMessage(aaAnswer.ReplyMessage, aaAnswer.ResultCode()); // Set ARAP AVPs. if (sm.AuthenticationInfo().AuthenticationType() != NASREQ_AUTHENTICATION_TYPE_ARAP) { AAA_LOG(LM_DEBUG, "[%N] Unacceptable auth type in multi-round auth.\n"); sm.Abort(); return; } ARAP_Info& arapInfo = (ARAP_Info&)sm.AuthenticationInfo(); aaAnswer.ArapSecurity = arapInfo.ArapSecurity(); aaAnswer.ArapSecurityData = arapInfo.ArapSecurityData(); if (arapInfo.PasswordRetry() != 0) aaAnswer.PasswordRetry = arapInfo.PasswordRetry(); sm.SendAA_Answer(); // Update the session state. sm.Session().Update(AAASession::EVENT_AUTH_CONTINUE); } }; class AcSendAA_AnswerWithSuccess : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AAA_LOG(LM_DEBUG, "[%N] Sending AA-Answer with a success Result-Code.\n"); AA_AnswerData& aaAnswer = sm.AA_Answer(); aaAnswer.ResultCode = AAA_SUCCESS; // Set ARAP-Challenge-Response AVP. if (sm.AuthenticationInfo().AuthenticationType() == NASREQ_AUTHENTICATION_TYPE_ARAP) { ARAP_Info& arapInfo = (ARAP_Info&)sm.AuthenticationInfo(); aaAnswer.ArapChallengeResponse = arapInfo.ArapChallengeResponse(); } sm.SendAA_Answer(); sm.Session().Update(AAASession::EVENT_AUTH_SUCCESS); } }; class AcSendAA_AnswerDueToAuthenticationFailure : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AA_AnswerData& aaAnswer = sm.AA_Answer(); AAA_LOG(LM_DEBUG, "[%N] Sending AA-Answer due to authentication failure.\n"); aaAnswer.ResultCode = AAA_AUTHENTICATION_REJECTED; // Set ARAP-Challenge-Response AVP. if (sm.AuthenticationInfo().AuthenticationType() == NASREQ_AUTHENTICATION_TYPE_ARAP) { ARAP_Info& arapInfo = (ARAP_Info&)sm.AuthenticationInfo(); if (arapInfo.PasswordRetry() != 0) aaAnswer.PasswordRetry = arapInfo.PasswordRetry(); } sm.SendAA_Answer(); sm.Session().Update(AAASession::EVENT_AUTH_FAILED); } }; class AcSendAA_AnswerDueToAuthorizationFailure : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AA_AnswerData& aaAnswer = sm.AA_Answer(); AAA_LOG(LM_DEBUG, "[%N] Sending AA-Answer due to authorization failure.\n"); aaAnswer.ResultCode = AAA_AUTHORIZATION_REJECTED; sm.SendAA_Answer(); sm.Session().Update(AAASession::EVENT_AUTH_FAILED); } }; class AcSendAA_AnswerDueToInvalidAA_Request : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { AA_AnswerData& aaAnswer = sm.AA_Answer(); AAA_LOG(LM_DEBUG, "[%N] Sending AA-Answer due to invalid AA-Request.\n"); aaAnswer.ResultCode = AAA_INVALID_AVP_VALUE; sm.Session().Update(AAASession::EVENT_AUTH_CONTINUE); sm.SendAA_Answer(); } }; class AcAuthorize : public DiameterNasreqServerAction { void operator()(DiameterNasreqServerStateMachine& sm) { if (sm.AuthorizationDone() || sm.Authorize()) sm.Event(DiameterNasreqServerStateMachine::EvSgAuthorizationSuccess); else sm.Event(DiameterNasreqServerStateMachine::EvSgAuthorizationFailure); } }; enum state { StInitialize, StWaitAA_Request, StCheckAA_Request, StWaitAuthorization, StAccepted, StRejected, StWaitAuthInfo, StTerminated }; enum { EvSgSuccess, EvSgLimitedSuccess, EvSgFailure, EvSgContinue, EvSgValid, EvSgInvalid }; AcSendAA_AnswerWithContinue acSendAA_AnswerWithContinue; AcSendAA_AnswerWithSuccess acSendAA_AnswerWithSuccess; AcSendAA_AnswerDueToAuthenticationFailure acSendAA_AnswerDueToAuthenticationFailure; AcSendAA_AnswerDueToAuthorizationFailure acSendAA_AnswerDueToAuthorizationFailure; AcSendAA_AnswerDueToInvalidAA_Request acSendAA_AnswerDueToInvalidAA_Request; AcForwardAuthInfo acForwardAuthInfo; AcCheckAA_Request acCheckAA_Request; AcAuthorize acAuthorize; // Defined as a leaf class DiameterNasreqServerStateTable_S() { AddStateTableEntry(StInitialize, DiameterNasreqServerStateMachine::EvRxAA_Request, StCheckAA_Request, acCheckAA_Request); AddStateTableEntry(StInitialize, DiameterNasreqServerStateMachine::EvSgDisconnect, StTerminated); AddWildcardStateTableEntry(StInitialize, StTerminated); AddStateTableEntry(StCheckAA_Request, DiameterNasreqServerStateMachine::EvSgValidAA_Request, StWaitAuthInfo, acForwardAuthInfo); AddStateTableEntry(StCheckAA_Request, DiameterNasreqServerStateMachine:: EvSgInvalidAA_Request, StRejected, acSendAA_AnswerDueToInvalidAA_Request); AddStateTableEntry(StWaitAA_Request, DiameterNasreqServerStateMachine::EvRxAA_Request, StCheckAA_Request, acCheckAA_Request); AddStateTableEntry(StWaitAA_Request, DiameterNasreqServerStateMachine::EvSgDisconnect, StTerminated); AddWildcardStateTableEntry(StWaitAA_Request, StTerminated); AddStateTableEntry(StWaitAuthInfo, DiameterNasreqServerStateMachine::EvRxAuthContinue, StWaitAA_Request, acSendAA_AnswerWithContinue); AddStateTableEntry(StWaitAuthInfo, DiameterNasreqServerStateMachine::EvRxAuthSuccess, StWaitAuthorization, acAuthorize); AddStateTableEntry(StWaitAuthInfo, DiameterNasreqServerStateMachine::EvRxAuthFailure, StRejected, acSendAA_AnswerDueToAuthenticationFailure); AddStateTableEntry(StWaitAuthInfo, DiameterNasreqServerStateMachine::EvSgDisconnect, StTerminated); AddWildcardStateTableEntry(StWaitAuthInfo, StTerminated); AddStateTableEntry(StWaitAuthorization, DiameterNasreqServerStateMachine:: EvSgAuthorizationSuccess, StAccepted, acSendAA_AnswerWithSuccess); AddStateTableEntry(StWaitAuthorization, DiameterNasreqServerStateMachine:: EvSgAuthorizationFailure, StRejected, acSendAA_AnswerDueToAuthorizationFailure); AddStateTableEntry(StWaitAuthorization, DiameterNasreqServerStateMachine::EvSgDisconnect, StTerminated); AddWildcardStateTableEntry(StWaitAuthorization, StTerminated); // Re-authentication AddStateTableEntry(StAccepted, DiameterNasreqServerStateMachine::EvRxAA_Request, StCheckAA_Request, acCheckAA_Request); AddStateTableEntry(StAccepted, DiameterNasreqServerStateMachine::EvSgDisconnect, StTerminated); AddWildcardStateTableEntry(StAccepted, StTerminated); AddWildcardStateTableEntry(StRejected, StRejected); AddWildcardStateTableEntry(StTerminated, StTerminated); InitialState(StInitialize); } ~DiameterNasreqServerStateTable_S() {}};typedef ACE_Singleton<DiameterNasreqServerStateTable_S, ACE_Recursive_Thread_Mutex> DiameterNasreqServerStateTable;DiameterNasreqServerStateMachine::DiameterNasreqServerStateMachine(DiameterNasreqServerSession& s, DiameterNasreqJobHandle &h) : AAA_StateMachine<DiameterNasreqServerStateMachine> (*this, *DiameterNasreqServerStateTable::instance(), "AAA_NASREQ_SERVER"), session(s), handle(h), authorizationDone(false){}void DiameterNasreqServerStateMachine::SendAA_Answer(){ AAAMessage msg; aaAnswerData.AuthApplicationId = NasreqApplicationId; AA_AnswerParser parser; parser.setAppData(&aaAnswerData); parser.setRawData(&msg); try { parser.parseAppToRaw(); } catch (DiameterParserError) { AAA_LOG(LM_ERROR, "[%N] Parsing error.\n"); return; } AAAMessageControl msgControl(Session().Self()); if (msgControl.Send(msg) != AAA_ERR_SUCCESS) { AAA_LOG(LM_ERROR, "Failed sending message.\n"); } else { AAA_LOG(LM_DEBUG, "Sent AA-Answer Message.\n"); }}boolDiameterNasreqServerStateMachine::CheckAA_Request(){ AA_RequestData& aaRequest = aaRequestData; AA_AnswerData& aaAnswer = aaAnswerData; // Validate Auth-Request-Type. if (!ValidateAuthRequestType(aaRequest.AuthRequestType())) { AAA_LOG(LM_ERROR, "[%N] Invalid auth request type.\n"); return false; } aaAnswer.AuthRequestType = aaRequest.AuthRequestType(); // If the Auth-Request-Type is AUTHORIZATION_ONLY, validation // completes with success. if (aaRequest.AuthRequestType() == AUTH_REQUEST_TYPE_AUTHORIZE_ONLY) return true; // If the authentication type is already chosen, skip the // authentication type selection procedure. if (authenticationInfo.get() != 0) { // This should be multi-round ARAP authentication. if (authenticationInfo->AuthenticationType() != NASREQ_AUTHENTICATION_TYPE_ARAP) { AAA_LOG(LM_ERROR, "[%N] Multi-round not allowed for PAP and CHAP.\n"); return false; } goto arap_multi_round_check; } // Authentication type selection procedure. // // Only one type of authentication information is chosen. The // authentication type is chosen in the following way: // // - If there is no User-Name AVP, then validation fails. // // - If there is a CHAP-Auth AVP, then CHAP is chosen as the // authentication type. // // - Else if there is a User-Password AVP, then PAP is chosen as the // authentication type. // // - Else if there is a ARAP-Password AVP, then ARAP is chosen as // the authentication type. // if (!aaRequest.UserName.IsSet()) { AAA_LOG(LM_DEBUG, "[%N] No username.\n"); return false; } if (aaRequest.ChapAuth.IsSet()) { if (!aaRequest.ChapChallenge.IsSet()) { AAA_LOG(LM_ERROR, "[%N] Missing CHAP-Challenge AVP.\n"); return false; } authenticationInfo = boost::shared_ptr<CHAP_Info> (new CHAP_Info(aaRequest.UserName(), aaRequest.ChapAuth(), aaRequest.ChapChallenge())); return true; } if (aaRequest.UserPassword.IsSet()) { authenticationInfo = boost::shared_ptr<PAP_Info> (new PAP_Info(aaRequest.UserName(), aaRequest.UserPassword())); return true; } if (aaRequest.ArapPassword.IsSet()) { if (!aaRequest.ArapChallengeResponse.IsSet()) { AAA_LOG(LM_ERROR, "[%N] Missing ARAP-Challenge-Response AVP.\n"); return false; } authenticationInfo = boost::shared_ptr<ARAP_Info> (new ARAP_Info(aaRequest.UserName(), aaRequest.ArapPassword(), aaRequest.ArapChallengeResponse())); return true; } // No authentication information is found. AAA_LOG(LM_ERROR, "[%N] No authentication information AVP.\n"); return false; arap_multi_round_check: do { if (!aaRequest.FramedProtocol.IsSet() || aaRequest.FramedProtocol()!= 3) goto state_check; if (!aaRequest.ArapSecurity.IsSet() || !aaRequest.ArapSecurityData.IsSet()) goto state_check; ARAP_Info &arapInfo = (ARAP_Info&)authenticationInfo; arapInfo.ArapSecurity() = aaRequest.ArapSecurity(); arapInfo.ArapSecurityData() = aaRequest.ArapSecurityData(); arapInfo.IsFirst() = false; } while(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -