📄 msipipsecapi.cxx
字号:
/* Copyright (C) 2004-2006 the Minisip Team 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 *//* Copyright (C) 2004 * * Authors: Joachim Orrblad <joachim@orrblad.com> **/#include <config.h>#include<libmutil/Timestamp.h>#include <libmutil/massert.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <linux/ipsec.h>#include<libminisip/ipsec/MsipIpsecAPI.h>#include <libmikey/keyagreement.h>#include <libmikey/MikeyCsIdMap.h>#include <libmikey/MikeyMessage.h>#include <libmikey/MikeyPayloadSP.h>#include <libmikey/MikeyException.h>#include <string.h>#include <unistd.h>#include <iostream>extern "C" {# include<libminisip/ipsec/libpfkey.h>}//---------------------------------------------------------------------------------------------------////---------------------------------------------------------------------------------------------------////Minisip IpSec API//---------------------------------------------------------------------------------------------------////ConstructorMsipIpsecAPI::MsipIpsecAPI(string localIpString, SipDialogSecurityConfig &securityConf) { so = pfkey_open(); massert(so >= 0); reqid = 0; //reqid = (u_int32_t)getpid(); seq = 3; securityConfig = securityConf; ka = NULL; offered = false; localIp = inet_addr(localIpString.c_str());}//DestructorMsipIpsecAPI::~MsipIpsecAPI(){ int i; list <MsipIpsecRequest *>::iterator iter; for( iter = madeREQ.begin(); iter != madeREQ.end() ; iter++ ){ i = (*iter)->remove(false); if(i == -1) fprintf( stderr, "Either a SA or a policy entry was not be removed, fix it!!!"); delete *iter; } pfkey_close(so); madeREQ.empty();}//-MsipIpsecAPI-PUBLIC-------------------------------------------------------------------------------////---------------------------------------------------------------------------------------------------//// Construct offer MIKEYMRef<SipMimeContent*> MsipIpsecAPI::getMikeyIpsecOffer(){ MikeyMessage * message; try{ switch( securityConfig.ka_type ){ case KEY_MGMT_METHOD_MIKEY_DH: if( !securityConfig.cert || securityConfig.cert->is_empty() ){ throw MikeyException( "No certificate provided for DH key agreement" ); } if( ka && ka->type() != KEY_AGREEMENT_TYPE_DH ){ ka = NULL; } if( !ka ){ ka = new KeyAgreementDH( securityConfig.cert, securityConfig.cert_db, DH_GROUP_OAKLEY5 ); } addSAToKa( ka->setdefaultPolicy(MIKEY_PROTO_IPSEC4) ); message = new MikeyMessage( ((KeyAgreementDH *)*ka) ); break; case KEY_MGMT_METHOD_MIKEY_PSK: ka = new KeyAgreementPSK( securityConfig.psk, securityConfig.psk_length ); addSAToKa( ka->setdefaultPolicy(MIKEY_PROTO_IPSEC4) ); ((KeyAgreementPSK *)*ka)->generateTgk(); message = new MikeyMessage( ((KeyAgreementPSK *)*ka) ); break; case KEY_MGMT_METHOD_MIKEY_PK: throw MikeyExceptionUnimplemented( "PK KA type not implemented" ); default: throw MikeyException( "Invalid type of KA" ); } string b64Message = message->b64Message(); delete message; return new SipMimeContent("application/mikey", b64Message, ""); } catch( certificate_exception & exc ){ // FIXME: tell the GUI merr << "Could not open certificate" << end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; return NULL; } catch( MikeyException & exc ){ merr << "MikeyException caught: " << exc->message() << end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec=false; return NULL; }}//---------------------------------------------------------------------------------------------------//// Handle offered MIKEYbool MsipIpsecAPI::setMikeyIpsecOffer(MRef<SipMimeContent*> MikeyM){ securityConfig.use_ipsec = true; if( MikeyM->getContentType() == "application/mikey"){ if( !responderAuthenticate( MikeyM->getString() ) ){ string errorString = "Incoming key management message could not be authenticated"; if( ka ){ errorString += ka->authError(); } return false; } else { //Here we set the offer in ka MikeyMessage * initMessage = (MikeyMessage *)ka->initiatorData(); switch( securityConfig.ka_type ){ case KEY_MGMT_METHOD_MIKEY_DH: initMessage->setOffer((KeyAgreementDH *)*ka); break; case KEY_MGMT_METHOD_MIKEY_PSK: initMessage->setOffer((KeyAgreementPSK *)*ka); break; case KEY_MGMT_METHOD_MIKEY_PK: /* Should not happen at this point */ throw MikeyExceptionUnimplemented("Public Key key agreement not implemented" ); break; default: throw MikeyExceptionMessageContent("Unexpected type of message in INVITE" ); } } } else{ securityConfig.use_ipsec = false; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; return false; } offered = true; return true;}//---------------------------------------------------------------------------------------------------//// Construct responder MIKEYMRef<SipMimeContent*> MsipIpsecAPI::getMikeyIpsecAnswer(){ if( securityConfig.use_ipsec && initMSipIpsec() ){ // string keyMgmtAnswer; // Generate the key management answer message if( ! ( securityConfig.ka_type & KEY_MGMT_METHOD_MIKEY ) ){ merr << "Unknown type of key agreement" << end; securityConfig.use_ipsec = false; return NULL; } MikeyMessage * responseMessage = NULL; MikeyMessage * initMessage = (MikeyMessage *)ka->initiatorData(); if( initMessage == NULL ){ merr << "Uninitialized message, this is a bug" << end; securityConfig.use_ipsec = false; return NULL; } try{ switch( securityConfig.ka_type ){ case KEY_MGMT_METHOD_MIKEY_DH: responseMessage = initMessage->buildResponse((KeyAgreementDH *)*ka); break; case KEY_MGMT_METHOD_MIKEY_PSK: responseMessage = initMessage->buildResponse((KeyAgreementPSK *)*ka); break; case KEY_MGMT_METHOD_MIKEY_PK: /* Should not happen at that point */ throw MikeyExceptionUnimplemented( "Public Key key agreement not implemented" ); break; default: throw MikeyExceptionMessageContent( "Unexpected type of message in INVITE" ); } } catch( certificate_exception & exc ){ // TODO: Tell the GUI merr << "Could not open certificate" <<end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; } catch( MikeyExceptionUnacceptable & exc ){ merr << "MikeyException caught: "<<exc->message()<<end; //FIXME! send SIP Unacceptable with Mikey Error message securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; } // Message was invalid catch( MikeyExceptionMessageContent & exc ){ MikeyMessage * error_mes; merr << "MikeyExceptionMesageContent caught: " << exc->message() << end; if( ( error_mes = exc->errorMessage() ) != NULL ) responseMessage = error_mes; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; } catch( MikeyException & exc ){ merr << "MikeyException caught: " << exc->message() << end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; } if( responseMessage != NULL && securityConfig.use_ipsec){ //if( ka && ka->type() == KEY_AGREEMENT_TYPE_DH ) // ((KeyAgreementDH *)*ka)->computeTgk(); if(start() == -1){ cerr << " I returned NULL, not good!" << flush << endl; return NULL; } return new SipMimeContent("application/mikey", responseMessage->b64Message(),""); } } return NULL;}//---------------------------------------------------------------------------------------------------////Handle responded MIKEYbool MsipIpsecAPI::setMikeyIpsecAnswer(MRef<SipMimeContent*> MikeyM){ if (MikeyM->getContentType() != "application/mikey") return false; if( !initiatorAuthenticate( MikeyM->getString() ) ){ string errorString = "Could not authenticate the key management message"; fprintf( stderr, "Auth failed\n"); return false; } if( ! ( securityConfig.ka_type & KEY_MGMT_METHOD_MIKEY ) ){ merr << "Unknown type of key agreement" << end; securityConfig.use_ipsec = false; return false; } MikeyMessage * responseMessage = NULL; try{ MikeyMessage * initMessage = (MikeyMessage *)ka->responderData(); if( initMessage == NULL ){ merr << "Uninitialized MIKEY init message, this is a bug" << end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; return false; } switch( securityConfig.ka_type ){ case KEY_MGMT_METHOD_MIKEY_DH: responseMessage = initMessage->parseResponse((KeyAgreementDH *)*ka); break; case KEY_MGMT_METHOD_MIKEY_PSK: responseMessage = initMessage->parseResponse((KeyAgreementPSK *)*ka); break; case KEY_MGMT_METHOD_MIKEY_PK: /* Should not happen at that point */ throw MikeyExceptionUnimplemented( "Public Key key agreement not implemented" ); break; default: throw MikeyExceptionMessageContent( "Unexpected type of message in INVITE" ); } } catch( certificate_exception & exc ){ // TODO: Tell the GUI merr << "Could not open certificate" <<end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; return false; } catch( MikeyExceptionUnacceptable & exc ){ merr << "MikeyException caught: "<<exc->message()<<end; //FIXME! send SIP Unacceptable with Mikey Error message securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; return false; } // Message was invalid catch( MikeyExceptionMessageContent & exc ){ MikeyMessage * error_mes; merr << "MikeyExceptionMesageContent caught: " << exc->message() << end; if( ( error_mes = exc->errorMessage() ) != NULL ){ responseMessage = error_mes; } securityConfig.ka_type = KEY_MGMT_METHOD_NULL; securityConfig.use_ipsec = false; return false; } catch( MikeyException & exc ){ merr << "MikeyException caught: " << exc->message() << end; securityConfig.ka_type = KEY_MGMT_METHOD_NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -