Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

pana_paa.cxx

00001 /* BEGIN_COPYRIGHT                                                        */
00002 /*                                                                        */
00003 /* Open Diameter: Open-source software for the Diameter and               */
00004 /*                Diameter related protocols                              */
00005 /*                                                                        */
00006 /* Copyright (C) 2002-2004 Open Diameter Project                          */
00007 /*                                                                        */
00008 /* This library is free software; you can redistribute it and/or modify   */
00009 /* it under the terms of the GNU Lesser General Public License as         */
00010 /* published by the Free Software Foundation; either version 2.1 of the   */
00011 /* License, or (at your option) any later version.                        */
00012 /*                                                                        */
00013 /* This library is distributed in the hope that it will be useful,        */
00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      */
00016 /* Lesser General Public License for more details.                        */
00017 /*                                                                        */
00018 /* You should have received a copy of the GNU Lesser General Public       */
00019 /* License along with this library; if not, write to the Free Software    */
00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    */
00021 /* USA.                                                                   */
00022 /*                                                                        */
00023 /* In addition, when you copy and redistribute some or the entire part of */
00024 /* the source code of this software with or without modification, you     */
00025 /* MUST include this copyright notice in each copy.                       */
00026 /*                                                                        */
00027 /* If you make any changes that are appeared to be useful, please send    */
00028 /* sources that include the changed part to                               */
00029 /* diameter-developers@lists.sourceforge.net so that we can reflect your  */
00030 /* changes to one unified version of this software.                       */
00031 /*                                                                        */
00032 /* END_COPYRIGHT                                                          */
00033 
00034 #include "pana_paa.h"
00035 #include "pana_serial_num.h"
00036 #include "pana_config_manager.h"
00037 #include "pana_cookie.h"
00038 
00039 void PANA_Paa::ReceiveDiscover()
00040 {
00041    PANA_Message &msg = *(m_RxMessageQueue.front());
00042    m_RxMessageQueue.pop_front();
00043 
00044    m_PeerDeviceId.clone(msg.srcDevices());
00045    m_PeerPort = msg.srcPort();
00046    
00047    if (PANA_CONFIG_AUTHAGENT().eap_piggyback_) {
00048        static_cast<PANA_PaaEventInterface&>(m_Event).EapStart
00049            (m_SeparateAuth);
00050        m_InStatefulDiscovery = true;
00051    }
00052    else {
00053        SendStartRequest(NULL);
00054    }
00055    delete &msg;
00056 }
00057 
00058 void PANA_Paa::Receive2ndEapStart()
00059 {
00060    PANA_Message &msg = *(m_RxMessageQueue.front());
00061    m_RxMessageQueue.pop_front();
00062 
00063    // cancel bind answer retry
00064    m_Timer.Cancel(PANA_TID_PBR_RETRY);
00065    m_RtQueue.ClearFront();
00066    
00067    static_cast<PANA_PaaEventInterface&>(m_Event).EapStart
00068        (m_SeparateAuth);
00069    delete &msg;
00070 }
00071 
00072 void PANA_Paa::ReceiveEapReAuth()
00073 {
00074     if (! m_RxMessageQueue.empty()) {
00075         PANA_Message *msg = m_RxMessageQueue.front();
00076         if (msg) {
00077             m_RxMessageQueue.pop_front();
00078             delete msg;
00079         }
00080     }
00081    
00082     BindResultReset();
00083     ReAuthenticate(PANA_REAUTH_EAP);
00084 }
00085 
00086 void PANA_Paa::ReceiveStartAnswer()
00087 {
00088    /* 
00089       When the PAA receives the PANA-Start-Answer message from the PaC, it
00090       verifies the cookie.  The cookie is considered as valid if the
00091       received cookie has the expected value.  If the computed cookie is
00092       valid, the protocol enters the authentication phase.  Otherwise, it
00093       MUST silently discard the received message.
00094 
00095       When a Cookie-AVP is carried in a PANA-Start-Request message, the
00096       initial EAP Request MUST NOT be carried in the PANA-Start-Request
00097       message in order for the PAA to be stateless.
00098 
00099       When a Cookie-AVP is not carried in a PANA-Start-Request message, the
00100       PAA does not need to be stateless.  In this case, the initial EAP
00101       Request message MAY be carried in the PANA-Start-Request message.
00102 
00103       If the initial EAP Request message is carried in the
00104       PANA-Start-Request message, an EAP Response message MUST be carried
00105       in the PANA-Start-Answer message returned to the PAA.
00106 
00107       In any case, PANA MUST NOT generate an EAP message on behalf of EAP
00108       peer or EAP (pass-through) authenticator.
00109 
00110       The PANA-Start-Request/Answer exchange is needed before entering
00111       authentication phase even when the PaC is pre-configured with PAAs IP
00112       address and the PANA-PAA-Discover message is unicast.
00113 
00114       A PANA-Start-Request message is never retransmitted. A
00115       PANA-Start-Answer message is retransmitted based on timer in the same
00116       manner as other messages retransmitted at PANA-layer.
00117 
00118       It is possible that both PAA and PaC initiate the discovery and
00119       initial handshake procedure at the same time, i.e., the PAA sends a
00120       PANA-Start-Request message while the PaC sends a PANA-PAA-Discover
00121       message.  To resolve the race condition, the PAA SHOULD silently
00122       discard the PANA-PAA-Discover message received from the PaC after it
00123       has sent a PANA-Start-Request message with creating a state for the
00124       PaC.
00125    */
00126     
00127    PANA_Message &msg = *(m_RxMessageQueue.front());
00128    m_RxMessageQueue.pop_front();
00129 
00130    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: Start answer [session], S-flag %d, tseq=%d, rseq=%d\n",
00131                        msg.flags().separate, msg.tseq(), msg.rseq()));
00132 
00133    AAAAvpContainer* c_sessionId = msg.avpList().search("Session-Id");
00134    if (c_sessionId == NULL) {
00135       throw (PANA_Exception(PANA_Exception::ENTRY_NOT_FOUND, 
00136                            "Session Id AVP not found in packet, discarding message"));
00137    }
00138    diameter_utf8string_t &sessionId = (*c_sessionId)
00139              [0]->dataRef(Type2Type<diameter_utf8string_t>());
00140 
00141    // save the attributes
00142    m_SessionId              = sessionId;
00143    m_InitialPaaTsec         = msg.rseq();
00144    m_InitialPacTsec         = msg.tseq();
00145    m_LastTransmittedTsec    = m_InitialPaaTsec;
00146    m_LastReceivedTsec       = msg.tseq();
00147    m_LastReceivedRsec       = msg.rseq();
00148    m_PeerPort               = msg.srcPort();
00149    m_LastPayload            = NULL;
00150    m_SessionLifetime        = PANA_CONFIG_AUTHAGENT().sessionLifetime_;
00151    m_SeparateAuth           = (PANA_CONFIG_AUTHAGENT().s_flag_) ? 
00152                               msg.flags().separate : 0;   
00153    m_ReqDeviceId            = PANA_DeviceId::TYPE(PANA_CONFIG_AUTHAGENT().request_dev_id_);
00154    m_PeerDeviceId.clone(msg.srcDevices());
00155    m_BindCount              = 0;
00156 
00157    // extract ISP information if any
00158    if (AAAAvpContainer *c_ispInfo = msg.avpList().search("ISP-Information")) {
00159 
00160       diameter_grouped_t &ispList = (*c_ispInfo)[0]->dataRef(Type2Type<diameter_grouped_t>());
00161 
00162       if (AAAAvpContainer *c_name = ispList.search("Provider-Name")) {
00163          m_PreferedISP.name_  = (*c_name)[0]->dataRef(Type2Type<diameter_utf8string_t>());
00164          ACE_DEBUG((LM_INFO, "(%P|%t)    Provider name = %s\n", m_PreferedISP.name_.data()));
00165       }
00166 
00167       if (AAAAvpContainer *c_id = ispList.search("Provider-Identifier")) {
00168          m_PreferedISP.id_ = (*c_id)[0]->dataRef(Type2Type<diameter_unsigned32_t>());
00169          ACE_DEBUG((LM_INFO, "(%P|%t)    Provider id = %d\n", m_PreferedISP.id_));
00170       }
00171       
00172       ACE_DEBUG((LM_INFO, "(%P|%t) Pac ISP preference: %s [ID: %d]\n",
00173                  m_PreferedISP.name_.data(), m_PreferedISP.id_));
00174    }
00175 
00176    if (PANA_CONFIG_AUTHAGENT().use_cookie_ ||
00177        (! PANA_CONFIG_AUTHAGENT().eap_piggyback_)) {
00178        static_cast<PANA_PaaEventInterface&>(m_Event).EapStart(m_SeparateAuth);
00179    }
00180    else {
00181        AAAAvpContainer* c_eapPayload = msg.avpList().search("EAP-Payload");
00182        if (c_eapPayload == NULL) {
00183            throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00184                            "No EAP payload found in PSA during piggyback"));
00185        }
00186         
00187        diameter_octetstring_t &eapPayload = (*c_eapPayload)[0]->
00188                    dataRef(Type2Type<diameter_octetstring_t>());
00189 
00190        AAAMessageBlock *block = AAAMessageBlock::Acquire
00191                    ((char*)eapPayload.data(), eapPayload.size());              
00192        static_cast<PANA_PaaEventInterface&>(m_Event).EapResponse
00193                    (block, m_SeparateAuth);
00194        block->Release();
00195    }
00196    delete &msg;
00197 }
00198 
00199 void PANA_Paa::SendStartRequest(AAAMessageBlock *request, PANA_PINFO type)
00200 {
00201    /*    
00202       PAA MAY enable NAP-ISP authentication separation by setting the
00203       S-flag of the message header of the PANA-Start-Request. Also, the
00204       PANA-Start-Request MAY contain zero or one NAP-Information AVP and
00205       zero or more ISP-Information AVPs to advertise the information on the
00206       NAP and/or ISPs.
00207 
00208        9.3.3 PANA-Start-Request (PSR)
00209 
00210          PANA-Start-Request (PSR) is sent by the PAA to the PaC. The PAA sets
00211          the transmission sequence number to an initial random value.  The
00212          received sequence number is set to zero (0).
00213 
00214               PANA-Start-Request ::= < PANA-Header: 2, REQ [SEP] >
00215                             [ Cookie ]
00216                             [ EAP-Payload ]
00217                             [ NAP-Information ]
00218                          *  [ ISP-Information ]
00219                          *  [ AVP ]
00220     */
00221 
00222    AAAAvpContainerManager cm;
00223    AAAAvpContainerEntryManager em;
00224    AAAAvpContainerEntry *e;
00225    PANA_Message *msg;
00226 
00227    ACE_NEW_NORETURN(msg, PANA_Message);
00228    if (msg == NULL) {
00229       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00230                             "Failed to allocate msg message"));
00231    }
00232 
00233    // Populate header
00234    PANA_MsgHeader::Flags flg = { 1, 0, 0, 0 };
00235    msg->flags(flg);
00236    msg->type(PANA_MTYPE_START);
00237    msg->tseq(PANA_SerialNumber::generateIsn());
00238    msg->rseq(0);
00239 
00240    // Calculate S-flag
00241    msg->flags().separate = PANA_CONFIG_AUTHAGENT().s_flag_;
00242 
00243    // Add EAP payload if any
00244    if (request) {
00245        AAAAvpContainer *c_eapPayload = cm.acquire("EAP-Payload");
00246 
00247        e = em.acquire(AAA_AVP_STRING_TYPE);
00248        diameter_octetstring_t &eapPayload = e->dataRef(Type2Type<diameter_octetstring_t>());
00249        c_eapPayload->add(e);
00250 
00251        // Add containers to listen
00252        msg->avpList().add(c_eapPayload);
00253 
00254        /*
00255           The EAP-Payload AVP (AVP Code 402) is of type OctetString and is used
00256           to encapsulate the actual EAP packet [RFC2284] that is being
00257           exchanged between the EAP client and the home Diameter server.
00258         */
00259 
00260        // Populate eap payload
00261        eapPayload.assign(request->base(), request->size());
00262    }
00263 
00264    // Populate NAP-Information 
00265    PANA_ProviderInfoTool infoTool;
00266    PANA_CfgProviderInfo *pInfo = &PANA_CONFIG_AUTHAGENT().nap_info_;
00267    if (pInfo->name_.length() > 0) {
00268 
00269       // Add the AVP's to containers
00270       AAAAvpContainer *c_napInfo = cm.acquire("NAP-Information");        
00271       e = em.acquire(AAA_AVP_GROUPED_TYPE);
00272       diameter_grouped_t &napInfo = e->dataRef(Type2Type<diameter_grouped_t>());
00273       c_napInfo->add(e);
00274 
00275       // Add containers to list and populate
00276       msg->avpList().add(c_napInfo);
00277       infoTool.Add(napInfo, *pInfo);
00278    }
00279 
00280    // See if there is also ISP-Info
00281    PANA_CfgProviderList &ispList = PANA_CONFIG_AUTHAGENT().isp_info_;
00282    if (ispList.size() > 0) {
00283 
00284       // Add containers to message
00285       AAAAvpContainer *c_ispInfo = cm.acquire("ISP-Information");        
00286       msg->avpList().add(c_ispInfo);
00287 
00288       PANA_CfgProviderList::iterator i;
00289       for (i = ispList.begin(); i != ispList.end(); i ++) {
00290 
00291          pInfo = (*i);
00292 
00293          // Add the AVP's to containers
00294          e = em.acquire(AAA_AVP_GROUPED_TYPE);
00295          diameter_grouped_t &ispInfo = e->dataRef(Type2Type<diameter_grouped_t>());
00296          c_ispInfo->add(e);
00297 
00298          // Add containers to list and populate
00299          PANA_ProviderInfoTool info;
00300          info.Add(ispInfo, *pInfo);
00301       }
00302    }
00303 
00304    // reset stateful flag
00305    m_InStatefulDiscovery = false;
00306 
00307    // send message
00308    DestinationAddressFormatting(*msg);
00309    m_TxChannel.Send(*this, *msg);
00310 
00311    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Start-Request, tseq=%d, rseq=%d\n",
00312               msg->tseq(), msg->rseq()));
00313 }
00314 
00315 void PANA_Paa::SendEapRequest(AAAMessageBlock *request, PANA_PINFO type)
00316 {
00317    /*
00318        PaC      PAA  Message(tseq,rseq)[AVPs] 
00319        ------------------------------------------------- 
00320                       (continued from discovery and initial handshake phase) 
00321            <-----     PANA-Auth-Request(x+1,y)[EAP{Request}] 
00322            ----->     PANA-Auth-Answer(y+1,x+1)[EAP{Response}] 
00323              . 
00324              . 
00325            <-----     PANA-Auth-Request (x+2,y+1)[EAP{Request}] 
00326            ----->     PANA-Auth-Answer (y+2,x+2)[EAP{Response}] 
00327            <-----     PANA-Bind-Request(x+3,y+2) // F-flag set 
00328                        [EAP{Success}, Device-Id, Protection-Cap., MAC]  
00329            ----->     PANA-Bind-Answer(y+3,x+3) 
00330                        [Device-Id, Protection-Cap., MAC] // F-flag set 
00331 
00332        9.3.5 PANA-Auth-Request (PAR)
00333 
00334            PANA-Auth-Request (PAR) is sent by the PAA to the PaC.
00335 
00336             PANA-Auth-Request ::= < PANA-Header: 3, REQ >
00337                            < Session-Id >
00338                            < EAP-Payload >
00339                         0*1 [ NAP-Information ]
00340                         0*1 [ ISP-Information ]
00341                          *  [ AVP ]
00342                         0*1 < MAC >
00343 
00344           (Both NAP-Information and ISP-Information MUST NOT be
00345            included at the same time)
00346    */
00347 
00348    AAAAvpContainerManager cm;
00349    AAAAvpContainerEntryManager em;
00350    PANA_Message *msg;
00351 
00352    ACE_NEW_NORETURN(msg, PANA_Message);
00353    if (msg == NULL) {
00354       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00355                            "Failed to allocate msg message"));
00356    }
00357 
00358    // Populate header
00359    PANA_MsgHeader::Flags flg = { 1, 0, 0, 0 };
00360    msg->flags(flg);
00361    msg->type(PANA_MTYPE_AUTH);
00362    msg->tseq(++ m_LastTransmittedTsec);
00363    msg->rseq(m_LastReceivedTsec);
00364 
00365    // Populate AVP's
00366    AAAAvpContainerEntry *e;
00367    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00368    AAAAvpContainer *c_eapPayload = cm.acquire("EAP-Payload");
00369 
00370    // Add the AVP's to containers
00371    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00372    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00373    c_sessionId->add(e);
00374 
00375    e = em.acquire(AAA_AVP_STRING_TYPE);
00376    diameter_octetstring_t &eapPayload = e->dataRef(Type2Type<diameter_octetstring_t>());
00377    c_eapPayload->add(e);
00378 
00379    // Add containers to listen
00380    msg->avpList().add(c_sessionId);
00381    msg->avpList().add(c_eapPayload);
00382 
00383    /*
00384       The EAP-Payload AVP (AVP Code 402) is of type OctetString and is used
00385       to encapsulate the actual EAP packet [RFC2284] that is being
00386       exchanged between the EAP client and the home Diameter server.
00387     */
00388 
00389    // Populate session id
00390    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00391    eapPayload.assign(request->base(), request->size());
00392 
00393    if (m_SeparateAuth) {
00394 
00395       ACE_DEBUG((LM_INFO, "(%P|%t) Separate NAP/ISP authentication supported\n"));
00396 
00397       /*
00398         When PaC and PAA negotiated during the discovery and initial
00399         handshake phase to perform separate NAP and ISP authentications in a
00400         single PANA session, the PAA determines the execution order of NAP
00401         authentication and ISP authentication.  In this case, the PAA can
00402         indicate which EAP authentication is currently occurring by including
00403         a NAP-Information or an ISP-Information AVP of the corresponding EAP
00404         authentication in the first PANA-Auth-Request message sent to the
00405         PaC. In the case where the PaC agreed to perform separate
00406         authentications but did not specify its ISP choice in
00407         PANA-Start-Answer message, the PAA MUST include its NAP-Information
00408         AVP in PANA-Auth-Request message when it performs NAP authentication
00409         and MUST NOT include any service provider information AVP when it
00410         performs ISP authentication so that the PaC can always distinguish
00411         ISP authentication from NAP authentication.  The PAA SHOULD stop
00412         including a NAP-Information or an ISP-Information AVP once it
00413         receives the first PANA-Auth-Answer message of the current EAP
00414         authentication.
00415       */
00416 
00417       PANA_CfgProviderInfo *pInfo = NULL;
00418       AAAAvpContainer *c_pInfo = NULL;
00419 
00420       switch (type) {
00421          case PANA_PINFO_ISP: 
00422             pInfo = &m_PreferedISP;
00423             c_pInfo = cm.acquire("ISP-Information");        
00424             break;
00425 
00426          case PANA_PINFO_NAP:
00427             pInfo = &PANA_CONFIG_AUTHAGENT().nap_info_;
00428             c_pInfo = cm.acquire("NAP-Information");        
00429             break;
00430 
00431          default:
00432             break;
00433       }
00434 
00435       if (pInfo && pInfo->name_.length() > 0) {
00436 
00437          // Add the AVP's to containers
00438          e = em.acquire(AAA_AVP_GROUPED_TYPE);
00439          diameter_grouped_t &group = e->dataRef(Type2Type<diameter_grouped_t>());
00440          c_pInfo->add(e);
00441 
00442          // Add containers to list and populate
00443          msg->avpList().add(c_pInfo);
00444          PANA_ProviderInfoTool infoTool;
00445          infoTool.Add(group, *pInfo);
00446       }
00447    }
00448 
00449    // send message
00450    DestinationAddressFormatting(*msg);
00451    m_TxChannel.Send(*this, *msg);
00452 
00453    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: EAP-Request, tseq=%d, rseq=%d\n",
00454               msg->tseq(), msg->rseq()));
00455 }
00456 
00457 void PANA_Paa::SendBindRequest(AAAMessageBlock *request, ACE_UINT32 rCode)
00458 {
00459    /*
00460        PaC      PAA  Message(tseq,rseq)[AVPs] 
00461        ------------------------------------------------- 
00462                       (continued from discovery and initial handshake phase) 
00463            <-----     PANA-Auth-Request(x+1,y)[EAP{Request}] 
00464            ----->     PANA-Auth-Answer(y+1,x+1)[EAP{Response}] 
00465              . 
00466              . 
00467            <-----     PANA-Auth-Request (x+2,y+1)[EAP{Request}] 
00468            ----->     PANA-Auth-Answer (y+2,x+2)[EAP{Response}] 
00469            <-----     PANA-Bind-Request(x+3,y+2) // F-flag set 
00470                        [EAP{Success}, Device-Id, Protection-Cap., MAC]  
00471            ----->     PANA-Bind-Answer(y+3,x+3) 
00472                        [Device-Id, Protection-Cap., MAC]  // F-flag set 
00473 
00474         9.3.7 PANA-Bind-Request (PBR)
00475 
00476             PANA-Bind-Request (PBR) is sent by the PAA to the PaC.
00477 
00478                PANA-Bind-Request ::= < PANA-Header: 4, REQ >
00479                            < Session-Id >
00480                            < Device-Id >
00481                            { EAP-Payload }
00482                            { Result-Code }
00483                            [ Session-Lifetime ]
00484                            [ Protection-Capability ]
00485                            [ Key-Id ]
00486                         *  [ EP-Device-Id ]
00487                         *  [ AVP ]
00488                        0*1 < MAC >
00489    */
00490 
00491    AAAAvpContainerManager cm;
00492    AAAAvpContainerEntryManager em;
00493    PANA_Message *msg;
00494 
00495    ACE_NEW_NORETURN(msg, PANA_Message);
00496    if (msg == NULL) {
00497       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00498                            "Failed to allocate msg message"));
00499    }
00500 
00501    // Populate header
00502    PANA_MsgHeader::Flags flg = { 1, 0, 0, 0 }; // TBD: bind request
00503    msg->flags(flg);
00504    msg->type(PANA_MTYPE_BIND);
00505    msg->tseq(++ m_LastTransmittedTsec);
00506    msg->rseq(m_LastReceivedTsec);
00507 
00508    // Populate AVP's
00509    AAAAvpContainerEntry *e;
00510    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00511    AAAAvpContainer *c_deviceId = cm.acquire("Device-Id");
00512    AAAAvpContainer *c_eapPayload = cm.acquire("EAP-Payload");
00513    AAAAvpContainer *c_resultCode = cm.acquire("Result-Code");
00514 
00515    // Add the AVP's to containers
00516    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00517    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00518    c_sessionId->add(e);
00519 
00520    e = em.acquire(AAA_AVPDataType(AAA_AVP_DEVICEID_TYPE));
00521    PANA_TVData_t &deviceId = e->dataRef(Type2Type<PANA_TVData_t>());
00522    c_deviceId->add(e);
00523 
00524    e = em.acquire(AAA_AVP_STRING_TYPE);
00525    diameter_octetstring_t &eapPayload = e->dataRef(Type2Type<diameter_octetstring_t>());
00526    c_eapPayload->add(e);
00527    
00528    e = em.acquire(AAA_AVP_UINTEGER32_TYPE);
00529    diameter_unsigned32_t &resultCode = e->dataRef(Type2Type<diameter_unsigned32_t>());
00530    c_resultCode->add(e);
00531 
00532    // Add containers to listen
00533    msg->avpList().add(c_sessionId);
00534    msg->avpList().add(c_deviceId);
00535    msg->avpList().add(c_eapPayload);
00536    msg->avpList().add(c_resultCode);
00537 
00538    // Populate required AVP's
00539    resultCode = rCode;
00540    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00541    eapPayload.assign(request->base(), request->size());
00542 
00543    switch (BindResult()) {
00544        case PANA_BIND_SUCCESS_FINAL: {
00545           diameter_unsigned32_t lifetime =
00546               PANA_CONFIG_AUTHAGENT().sessionLifetime_ +
00547               PANA_CONFIG_AUTHAGENT().gracePeriod_;
00548           if (lifetime > 0) {
00549               AAAAvpContainer *c_sessionLifetime = cm.acquire("Session-Lifetime");
00550        
00551               e = em.acquire(AAA_AVP_UINTEGER32_TYPE);
00552               diameter_unsigned32_t &sessionLifetime = e->dataRef
00553                   (Type2Type<diameter_unsigned32_t>());
00554               c_sessionLifetime->add(e);
00555 
00556               sessionLifetime = lifetime;
00557               msg->avpList().add(c_sessionLifetime);
00558           }
00559        }
00560        // fall through
00561        case PANA_BIND_INTERIM: {
00562           diameter_unsigned32_t protectionCap = PANA_PCAP_UNKNOWN;
00563           if (PANA_CONFIG_GENERAL().protection_capability_ > 0) {
00564               AAAAvpContainer *c_protectionCap = cm.acquire
00565                   ("Protection-Capability");
00566        
00567               e = em.acquire(AAA_AVP_UINTEGER32_TYPE);
00568               protectionCap = e->dataRef(Type2Type<diameter_unsigned32_t>());
00569               c_protectionCap->add(e);
00570 
00571               protectionCap = PANA_CONFIG_GENERAL().protection_capability_;
00572               msg->avpList().add(c_protectionCap);
00573           }
00574 
00575           if (m_SA.MSK().length() > 0) {
00576              AAAAvpContainer *c_keyId = cm.acquire("Key-Id");
00577              e = em.acquire(AAA_AVP_INTEGER32_TYPE);
00578              diameter_integer32_t &keyId = e->dataRef
00579                  (Type2Type<diameter_integer32_t>());
00580              c_keyId->add(e);
00581 
00582              msg->avpList().add(c_keyId);
00583              keyId = m_SA.KeyId();
00584           }
00585 
00586           /*
00587             4.11 Support for Separate EP
00588 
00589               PANA allows PAA and EP to be separate entities.  In this case,
00590               if data traffic protection needs to be initiated after successful
00591               PANA authentication phase, PaC needs to know the device identifier
00592               of EP(s) so that it is able to establish a security association
00593               with each EP to protect data traffic.
00594 
00595               To this end, when a Protection-Capability AVP with either
00596               L2_PROTECTION or IPSEC_PROTECTION in the AVP payload is carried
00597               in a PANA-Bind-Request message and if there is an EP that has a
00598               different device identifier than that of the PAA, one or more
00599               EP-Device-Id AVPs MUST also be carried in the PANA-Bind-Request
00600               message.  In this case, if one EP has the same device identifier
00601               as the PAA, an EP-Device-Id AVP that contains the device identifier
00602               of the EP (i.e., the PAA) MUST also be included in the
00603               PANA-Bind-Request.
00604            */
00605            if (((protectionCap == PANA_PCAP_L2) ||
00606                 (protectionCap == PANA_PCAP_IPSEC)) &&
00607                (! PANA_CONFIG_AUTHAGENT().ep_id_.empty())) {
00608        
00609                AAAAvpContainer *c_epDeviceId = cm.acquire("EP-Device-Id");
00610                msg->avpList().add(c_epDeviceId);
00611        
00612                PANA_DeviceIdIterator i = PANA_CONFIG_AUTHAGENT().ep_id_.begin();
00613                for (;i != PANA_CONFIG_AUTHAGENT().ep_id_.end(); i++) {
00614 
00615                    PANA_DeviceId *id = (*i);
00616   
00617                    // Add the AVP's to containers
00618                    e = em.acquire(AAA_AVPDataType(AAA_AVP_DEVICEID_TYPE));
00619                    PANA_TVData_t &deviceId = e->dataRef(Type2Type<PANA_TVData_t>());
00620                    c_epDeviceId->add(e);
00621 
00622                    deviceId.type = id->type();
00623                    std::string &value = const_cast<std::string&>(id->id());
00624                    deviceId.value.assign(value.data(), value.size());
00625                }
00626            }
00627        }
00628        break;
00629        case PANA_BIND_SUCCESS_INITIAL:
00630        case PANA_BIND_FAILED:
00631        default:
00632            break;
00633    }
00634 
00635    /*
00636      The EAP-Payload AVP (AVP Code 402) is of type OctetString and is used
00637      to encapsulate the actual EAP packet [RFC2284] that is being
00638      exchanged between the EAP client and the home Diameter server.
00639     */
00640    
00641    // resolve source address
00642    PANA_DeviceIdContainer srcDevices;
00643    m_TxChannel.GetLocalAddress(srcDevices);
00644 
00645    PANA_DeviceId *id = srcDevices.search(m_ReqDeviceId);
00646    if (id == NULL) {
00647       // default is IPV4
00648       id = srcDevices.search(PANA_DeviceId::IPV4_ADDRESS);
00649       if (id == NULL) {
00650          throw (PANA_Exception(PANA_Exception::FAILED, 
00651                "No IPV4/MAC address given in the peer device list"));
00652       }
00653       m_ReqDeviceId = PANA_DeviceId::IPV4_ADDRESS;
00654    }
00655    deviceId.type = id->type();
00656    deviceId.value.assign(id->id().data(), id->id().size());
00657 
00658    // send message
00659    DestinationAddressFormatting(*msg, request);
00660    m_TxChannel.Send(*this, *msg);
00661 
00662    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Bind-Request, tseq=%d, rseq=%d, keyId=%d\n",
00663               msg->tseq(), msg->rseq(), m_SA.KeyId()));
00664    
00665   PANA_RtQueueMsgBlockDataWithRcode data(request, rCode);
00666   if (m_RtQueue.Schedule(data)) {
00667       m_Timer.Schedule(PANA_TID_PBR_RETRY, data.Timeout());       
00668   }
00669 }
00670 
00671 void PANA_Paa::RetryBindRequest()
00672 {
00673    m_Timer.Cancel(PANA_TID_PBR_RETRY);
00674    
00675    PANA_RtQueueData *data = NULL;
00676    if (m_RtQueue.ReSchedule(data)) {
00677        SendBindRequest(static_cast<PANA_RtQueueMsgBlockDataWithRcode*>(data)->MsgBlock(), 
00678                    static_cast<PANA_RtQueueMsgBlockDataWithRcode*>(data)->RCode());
00679        m_Timer.Schedule(PANA_TID_PBR_RETRY, data->Timeout());       
00680    }
00681    else {
00682        m_Timer.Schedule(PANA_TID_DISCONNECT, 0);
00683    }
00684 }
00685 
00686 void PANA_Paa::ReceiveBindAnswer()
00687 {
00688    PANA_Message &msg = *(m_RxMessageQueue.front());
00689    m_RxMessageQueue.pop_front();
00690 
00691    AAAAvpContainer* c_deviceId = msg.avpList().search("Device-Id");
00692    if (c_deviceId) {
00693        PANA_TVData_t &deviceId = (*c_deviceId)[0]->dataRef(Type2Type<PANA_TVData_t>());
00694        if (m_ReqDeviceId == deviceId.type) {
00695            PANA_DeviceId id(PANA_DeviceId::TYPE(deviceId.type), deviceId.value);
00696            PANA_DeviceId *knownId = m_PeerDeviceId.search(PANA_DeviceId::TYPE(deviceId.type));
00697            if (knownId && !(*knownId == id)) {
00698                throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00699                             "Device id type in bind answer does not match known peer id"));
00700            }
00701            else if (! knownId) {
00702                m_PeerDeviceId.clone(id);
00703            }
00704            m_Event.AuthorizePeer(id, false);
00705        }
00706        else {
00707            throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00708                            "Device id type in bind answer does not match request"));
00709        }
00710    }
00711 
00712    // cancel bind answer retry
00713    m_Timer.Cancel(PANA_TID_PBR_RETRY);
00714    m_RtQueue.ClearFront();   
00715    delete &msg;
00716 }
00717 
00718 void PANA_Paa::ReceiveEapResponse()
00719 {
00720    PANA_Message &msg = *(m_RxMessageQueue.front());
00721    m_RxMessageQueue.pop_front();
00722 
00723    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: Auth answer, S-flag %d, tseq=%d, rseq=%d\n",
00724                        msg.flags().separate, msg.tseq(), msg.rseq()));
00725 
00726    AAAAvpContainer* c_eapPayload = msg.avpList().search("EAP-Payload");
00727    if (c_eapPayload == NULL) {
00728       throw (PANA_Exception(PANA_Exception::ENTRY_NOT_FOUND, 
00729                            "EAP-Payload AVP not found in packet, discarding message"));
00730    }
00731 
00732    diameter_octetstring_t &eapPDU = (*c_eapPayload)
00733               [0]->dataRef(Type2Type<diameter_octetstring_t>());
00734    AAAMessageBlock *eapBlock = AAAMessageBlock::Acquire((char*)eapPDU.data(), eapPDU.size());
00735    static_cast<PANA_PaaEventInterface&>(m_Event).EapResponse(eapBlock, m_SeparateAuth);
00736    eapBlock->Release();
00737    delete &msg;
00738 }
00739 
00740 void PANA_Paa::DestinationAddressFormatting(PANA_Message &msg,
00741                                             AAAMessageBlock *eapPayload)
00742 {
00743    // Save the payload
00744    if (eapPayload) {
00745       if (m_LastPayload) {
00746          m_LastPayload->Release();
00747       }
00748       m_LastPayload = AAAMessageBlock::Acquire(eapPayload);
00749    }
00750 
00751    msg.srcPort(m_PeerPort);
00752    msg.srcDevices().clone(m_PeerDeviceId);
00753 }
00754 
00755 void PANA_Paa::ValidateCookie(PANA_Message &psa) throw(PANA_Exception)
00756 {
00757    // extract cookie
00758    AAAAvpContainer *c_cookie = psa.avpList().search("Cookie");
00759    if (c_cookie == NULL) {
00760       throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00761                            "Missing cookie AVP in start answer message"));
00762    }
00763    diameter_octetstring_t &cookie = (*c_cookie)[0]->dataRef(Type2Type<diameter_octetstring_t>());
00764 
00765    // convert address 
00766    PANA_DeviceIdContainer &cntr = psa.srcDevices();
00767    PANA_DeviceId *ipId = cntr.search(PANA_DeviceId::IPV4_ADDRESS);
00768    PANA_DeviceId *hwId = cntr.search(PANA_DeviceId::LL_ADDRESS);
00769 
00770    ACE_DEBUG((LM_INFO, "(%P|%t) Validating cookie\n"));
00771 
00772    // verify cookie with source device id
00773    if ((PANA_COOKIE_VERIFY(const_cast<std::string&>(ipId->id()), cookie) == false)) {
00774        // now try mac address
00775        if (PANA_COOKIE_VERIFY(const_cast<std::string&>(hwId->id()), cookie) == false) {
00776           throw (PANA_Exception(PANA_Exception::FAILED, 
00777                                "Received start answer with invalid cookie"));
00778        }
00779    }
00780 }
00781 

Generated on Fri Jun 25 19:18:29 2004 for PANA by doxygen 1.3.5