Mixe for Privacy and Anonymity in the Internet
CALastMix.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000, The JAP-Team
00003 All rights reserved.
00004 Redistribution and use in source and binary forms, with or without modification,
00005 are permitted provided that the following conditions are met:
00006 
00007   - Redistributions of source code must retain the above copyright notice,
00008     this list of conditions and the following disclaimer.
00009 
00010   - Redistributions in binary form must reproduce the above copyright notice,
00011     this list of conditions and the following disclaimer in the documentation and/or
00012     other materials provided with the distribution.
00013 
00014   - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
00015     may be used to endorse or promote products derived from this software without specific
00016     prior written permission.
00017 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00027 */
00028 #include "StdAfx.h"
00029 #ifndef ONLY_LOCAL_PROXY
00030 #include "CALastMix.hpp"
00031 #ifdef NEW_MIX_TYPE // TypeB mixes
00032   #include "TypeB/typedefsb.hpp"
00033 #else // not TypeB mixes
00034   /* TypeB mixes doesn't use the default-implementation */
00035   #include "CALastMixChannelList.hpp"
00036 #endif
00037 #include "CALibProxytest.hpp"
00038 #include "CASocketGroup.hpp"
00039 #include "CASingleSocketGroup.hpp"
00040 #include "CAMsg.hpp"
00041 #include "CACmdLnOptions.hpp"
00042 #ifdef HAVE_UNIX_DOMAIN_PROTOCOL
00043   #include "CASocketAddrUnix.hpp"
00044 #endif
00045 #include "CACertStore.hpp"
00046 #include "CABase64.hpp"
00047 #include "CAPool.hpp"
00048 #include "xml/DOM_Output.hpp"
00049 #include "CAStatusManager.hpp"
00050 /*******************************************************************************/
00051 // ----------START NEW VERSION -----------------------
00052 //---------------------------------------------------------
00053 /********************************************************************************/
00054 
00055 SINT32 CALastMix::initOnce()
00056   {
00057     SINT32 ret=CAMix::initOnce();
00058     if(ret!=E_SUCCESS)
00059       return ret;
00060     if(setTargets()!=E_SUCCESS)
00061       {
00062         CAMsg::printMsg(LOG_CRIT,"Could not set Targets (proxies)!\n");
00063         return E_UNKNOWN;
00064       }
00065 
00066     //m_pSignature=CALibProxytest::getOptions()->getSignKey();
00067     m_pMultiSignature=CALibProxytest::getOptions()->getMultiSigner();
00068     if(m_pMultiSignature==NULL)
00069       return E_UNKNOWN;
00070     if(CALibProxytest::getOptions()->getListenerInterfaceCount()<1)
00071       {
00072         CAMsg::printMsg(LOG_CRIT,"No ListenerInterfaces specified!\n");
00073         return E_UNKNOWN;
00074       }
00075     if(CALibProxytest::getOptions()->getCascadeXML() != NULL)
00076       initMixCascadeInfo(CALibProxytest::getOptions()->getCascadeXML());
00077     return E_SUCCESS;
00078   }
00079 
00080 SINT32 CALastMix::init()
00081   {
00082     m_pRSA=new CAASymCipher();
00083 #ifdef EXPORT_ASYM_PRIVATE_KEY
00084     if(CALibProxytest::getOptions()->isImportKey())
00085       {
00086         UINT32 keyFileBuffLen=8096;
00087         UINT8* keyFileBuff=new UINT8[keyFileBuffLen];
00088         CALibProxytest::getOptions()->getEncryptionKeyImportFile(keyFileBuff,keyFileBuffLen);
00089         UINT8* keyBuff=readFile(keyFileBuff,&keyFileBuffLen);
00090         m_pRSA->setPrivateKeyAsXML(keyBuff,keyFileBuffLen);
00091         delete[] keyFileBuff;
00092         delete[] keyBuff;
00093       }
00094     else
00095 #endif
00096       {
00097         if(m_pRSA->generateKeyPair(1024)!=E_SUCCESS)
00098           {
00099             CAMsg::printMsg(LOG_CRIT,"Could not generate a valid key pair\n");
00100             return E_UNKNOWN;
00101           }
00102       }
00103 #ifdef EXPORT_ASYM_PRIVATE_KEY
00104     if(CALibProxytest::getOptions()->isExportKey())
00105       {
00106         UINT32 keyFileBuffLen=8096;
00107         UINT8* keyFileBuff=new UINT8[keyFileBuffLen];
00108         UINT8* keyBuff=new UINT8[keyFileBuffLen];
00109         CALibProxytest::getOptions()->getEncryptionKeyExportFile(keyFileBuff,keyFileBuffLen);
00110         m_pRSA->getPrivateKeyAsXML(keyBuff,&keyFileBuffLen);
00111         saveFile(keyFileBuff,keyBuff,keyFileBuffLen);
00112         delete[] keyFileBuff;
00113         delete[] keyBuff;
00114       }
00115 #endif
00116 
00117     CAListenerInterface*  pListener=NULL;
00118     UINT32 interfaces=CALibProxytest::getOptions()->getListenerInterfaceCount();
00119     for(UINT32 i=1;i<=interfaces;i++)
00120       {
00121         pListener=CALibProxytest::getOptions()->getListenerInterface(i);
00122         if(!pListener->isVirtual())
00123           break;
00124         delete pListener;
00125         pListener=NULL;
00126       }
00127     if(pListener==NULL)
00128       {
00129         CAMsg::printMsg(LOG_CRIT,"Initialization failed! Reason: No usable (non virtual) interface was found! Hint: Virtual interfaces only needed if you are behind a NAT/network address translation, and therefore have to publish other external IP addresses to the InfoServices than your internal/hidden IP addresses.\n");
00130         return E_UNKNOWN;
00131       }
00132 
00133     const CASocketAddr* pAddr=NULL;
00134     pAddr=pListener->getAddr();
00135     delete pListener;
00136     pListener = NULL;
00137     UINT8 buff[255];
00138     pAddr->toString(buff,255);
00139 
00140     CAMsg::printMsg(LOG_INFO,"Waiting for connection from previous Mix on %s...\n", buff);
00141 
00142     m_pMuxIn=new CAMuxSocket();
00143     SINT32 ret=m_pMuxIn->accept(*pAddr);
00144     delete pAddr;
00145     pAddr = NULL;
00146     if(ret!=E_SUCCESS)
00147         {
00148         CAMsg::printMsg(LOG_CRIT,"Initialization failed! Reason: Call to accept() failed with error '%s' (%i)\n", 
00149           GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00150         return ret;
00151         }
00152     // connected to previous mix
00153     m_pMuxIn->getCASocket()->setRecvBuff(500*MIXPACKET_SIZE);
00154     m_pMuxIn->getCASocket()->setSendBuff(500*MIXPACKET_SIZE);
00155     m_pMuxIn->getCASocket()->setKeepAlive((UINT32)1800);
00156 
00157     MONITORING_FIRE_NET_EVENT(ev_net_prevConnected);
00158     CAMsg::printMsg(LOG_INFO,"connected!\n");
00159 
00160 #ifdef LOG_CRIME
00161     m_nCrimeRegExpsURL=NULL;
00162     m_pCrimeRegExpsURL=CALibProxytest::getOptions()->getCrimeRegExpsURL(&m_nCrimeRegExpsURL);
00163     m_nCrimeRegExpsPayload = NULL;
00164     m_pCrimeRegExpsPayload = CALibProxytest::getOptions()->getCrimeRegExpsPayload(&m_nCrimeRegExpsPayload);
00165 #endif
00166     ret=processKeyExchange();
00167     if(ret!=E_SUCCESS)
00168     {
00169       MONITORING_FIRE_NET_EVENT(ev_net_keyExchangePrevFailed);
00170       return ret;
00171     }
00172     MONITORING_FIRE_NET_EVENT(ev_net_keyExchangePrevSuccessful);
00173     //keyexchange successful
00174 #ifdef REPLAY_DETECTION
00175     m_pReplayDB=new CADatabase();
00176     m_pReplayDB->start();
00177 #endif
00178     m_pQueueSendToMix=new CAQueue(sizeof(tQueueEntry));
00179     m_pQueueReadFromMix=new CAQueue(sizeof(tQueueEntry));
00180 
00181     m_pMuxInControlChannelDispatcher=new CAControlChannelDispatcher(m_pQueueSendToMix,NULL,0);
00182 #ifdef REPLAY_DETECTION
00183     m_pReplayMsgProc=new CAReplayCtrlChannelMsgProc(this);
00184     m_pReplayMsgProc->startTimeStampPorpagation(REPLAY_TIMESTAMP_PROPAGATION_INTERVALL);
00185     m_u64ReferenceTime=time(NULL);
00186 #endif
00187 
00188     m_bRestart=false;
00189     //Starting thread for Step 1a
00190     m_pthreadReadFromMix=new CAThread((UINT8*)"CALastMix - ReadFromMix");
00191     m_pthreadReadFromMix->setMainLoop(lm_loopReadFromMix);
00192     m_pthreadReadFromMix->start(this);
00193 
00194     //Starting thread for Step 4
00195     m_pthreadSendToMix=new CAThread((UINT8*)"CALastMix - SendToMix");
00196     m_pthreadSendToMix->setMainLoop(lm_loopSendToMix);
00197     m_pthreadSendToMix->start(this);
00198 
00199     //Starting thread for logging
00200 #ifdef LOG_PACKET_TIMES
00201     m_pLogPacketStats=new CALogPacketStats();
00202     m_pLogPacketStats->setLogIntervallInMinutes(LM_PACKET_STATS_LOG_INTERVALL);
00203     m_pLogPacketStats->start();
00204 #endif
00205     #ifndef NEW_MIX_TYPE // not TypeB mixes
00206       /* TypeB mixes are using an own implementation */
00207     m_pChannelList=new CALastMixChannelList;
00208     #endif
00209     return E_SUCCESS;
00210   }
00211 
00222 SINT32 CALastMix::processKeyExchange()
00223   {
00224     XERCES_CPP_NAMESPACE::DOMDocument* doc=createDOMDocument();
00225     DOMElement* elemMixes=createDOMElement(doc,"Mixes");
00226     setDOMElementAttribute(elemMixes,"count",(UINT32)1);
00227     //UINT8 cName[128];
00228     //CALibProxytest::getOptions()->getCascadeName(cName,128);
00229     //setDOMElementAttribute(elemMixes,"cascadeName",cName);
00230     doc->appendChild(elemMixes);
00231 
00232     addMixInfo(elemMixes, false);
00233     DOMElement* elemMix=NULL;
00234     getDOMChildByName(elemMixes, "Mix", elemMix, false);
00235 
00236     //Inserting MixProtocol Version
00237     // Version 0.3  - "normal", initial mix protocol
00238     // Version 0.4  - with new flow control [was only used for tests]
00239     // Version 0.5  - end-to-end 1:n channels (only between client and last mix)
00240     // Version 0.6  - with new flow control for downstream [productive]
00241     // Version 0.7  - with new flow control for downstream AND upstream
00242     DOMElement* elemMixProtocolVersion=createDOMElement(doc,"MixProtocolVersion");
00243     elemMix->appendChild(elemMixProtocolVersion);
00244     #ifdef NEW_MIX_TYPE // TypeB mixes
00245       setDOMElementValue(elemMixProtocolVersion,(UINT8*)"0.5");
00246       DOM_Element elemDownstreamPackets = doc.createElement("DownstreamPackets");
00247       setDOMElementValue(elemDownstreamPackets, (UINT32)CHANNEL_DOWNSTREAM_PACKETS);
00248       elemMixProtocolVersion.appendChild(elemDownstreamPackets);
00249       DOM_Element elemChannelTimeout = doc.createElement("ChannelTimeout");
00250       /* let the client use our channel-timeout + 5 seconds */
00251       setDOMElementValue(elemChannelTimeout, (UINT32)(CHANNEL_TIMEOUT + 5));
00252       elemMixProtocolVersion.appendChild(elemChannelTimeout);
00253       DOM_Element elemChainTimeout = doc.createElement("ChainTimeout");
00254       /* let the client use our chain-timeout - 5 seconds */
00255       setDOMElementValue(elemChainTimeout, (UINT32)(CHAIN_TIMEOUT - 5));
00256       elemMixProtocolVersion.appendChild(elemChainTimeout);
00257     #else
00258       setDOMElementValue(elemMixProtocolVersion,(UINT8*)"0.6");
00259       DOMElement* elemFlowControl=createDOMElement(doc,"FlowControl");
00260       DOMElement* elemUpstreamSendMe=createDOMElement(doc,"UpstreamSendMe");
00261       DOMElement* elemDownstreamSendMe=createDOMElement(doc,"DownstreamSendMe");
00262       elemMix->appendChild(elemFlowControl);
00263       elemFlowControl->appendChild(elemUpstreamSendMe);
00264       elemFlowControl->appendChild(elemDownstreamSendMe);
00265       setDOMElementValue(elemUpstreamSendMe,(UINT32)FLOW_CONTROL_SENDME_SOFT_LIMIT);
00266       setDOMElementValue(elemDownstreamSendMe,(UINT32)FLOW_CONTROL_SENDME_SOFT_LIMIT);
00267       setDOMElementAttribute(elemFlowControl,"withUpstreamFlowControl",true);
00268     #endif
00269     //Inserting RSA-Key
00270     DOMElement* nodeRsaKey=NULL;
00271     m_pRSA->getPublicKeyAsDOMElement(nodeRsaKey,doc);
00272     elemMix->appendChild(nodeRsaKey);
00273 
00274     appendCompatibilityInfo(elemMix);
00275 
00276     //inserting Nonce
00277     DOMElement* elemNonce=createDOMElement(doc,"Nonce");
00278     UINT8 arNonce[16];
00279     getRandom(arNonce,16);
00280     UINT8 tmpBuff[50];
00281     UINT32 tmpLen=50;
00282     CABase64::encode(arNonce,16,tmpBuff,&tmpLen);
00283     tmpBuff[tmpLen]=0;
00284     setDOMElementValue(elemNonce,tmpBuff);
00285     elemMix->appendChild(elemNonce);
00286 
00287 
00288 
00289 // Add Info about KeepAlive traffic
00290     DOMElement* elemKeepAlive=NULL;
00291     UINT32 u32KeepAliveSendInterval=CALibProxytest::getOptions()->getKeepAliveSendInterval();
00292     UINT32 u32KeepAliveRecvInterval=CALibProxytest::getOptions()->getKeepAliveRecvInterval();
00293     elemKeepAlive=createDOMElement(doc,"KeepAlive");
00294     DOMElement* elemKeepAliveSendInterval=NULL;
00295     DOMElement* elemKeepAliveRecvInterval=NULL;
00296     elemKeepAliveSendInterval=createDOMElement(doc,"SendInterval");
00297     elemKeepAliveRecvInterval=createDOMElement(doc,"ReceiveInterval");
00298     elemKeepAlive->appendChild(elemKeepAliveSendInterval);
00299     elemKeepAlive->appendChild(elemKeepAliveRecvInterval);
00300     setDOMElementValue(elemKeepAliveSendInterval,u32KeepAliveSendInterval);
00301     setDOMElementValue(elemKeepAliveRecvInterval,u32KeepAliveRecvInterval);
00302     elemMix->appendChild(elemKeepAlive);
00303 
00304     CAMsg::printMsg(LOG_DEBUG,"KeepAlive-Traffic: Offering -- SendInterval %u -- Receive Interval %u\n",u32KeepAliveSendInterval,u32KeepAliveRecvInterval);
00305 
00306     /* append the terms and conditions, if there are any, to the KeyInfo
00307      * Extensions, (nodes that can be removed from the KeyInfo without
00308      * destroying the signature of the "Mix"-node).
00309      */
00310     if(CALibProxytest::getOptions()->getTermsAndConditions() != NULL)
00311     {
00312       appendTermsAndConditionsExtension(doc, elemMixes);
00313       elemMix->appendChild(termsAndConditionsInfoNode(doc));
00314     }
00315 
00316     // create signature
00317     if (signXML(elemMix) != E_SUCCESS)
00318     {
00319       CAMsg::printMsg(LOG_DEBUG,"Could not sign KeyInfo sent to users...\n");
00320     }
00321 
00322     UINT32 len=0;
00323     UINT8* messageBuff=DOM_Output::dumpToMem(doc,&len);
00324     if (doc != NULL)
00325     {
00326       doc->release();
00327       doc = NULL;
00328     }
00329     UINT32 tmp = htonl(len);
00330     CAMsg::printMsg(LOG_INFO,"Sending Infos (chain length and RSA-Key, Message-Size %u)\n",len);
00331 
00332     if (len > 100000)
00333     {
00334       CAMsg::printMsg(LOG_WARNING,"Unrealistic length for key info: %u We might not be able to get a connection.\n",len);
00335     }
00336     
00337     if( (m_pMuxIn->getCASocket()->send((UINT8*)&tmp, sizeof(tmp)) != sizeof(tmp)) ||
00338         m_pMuxIn->getCASocket()->send(messageBuff,len)!=(SINT32)len)
00339     {
00340       CAMsg::printMsg(LOG_ERR,"Error sending Key-Info!\n");
00341       delete []messageBuff;
00342       messageBuff = NULL;
00343       return E_UNKNOWN;
00344     }
00345     delete[] messageBuff;
00346     messageBuff = NULL;
00347 
00348     SINT32 ret;
00349     //Now receiving the symmetric key
00350     CAMsg::printMsg(LOG_INFO,"Waiting for length of symmetric key from previous Mix...\n");
00351     if((ret = m_pMuxIn->receiveFully((UINT8*) &tmp, sizeof(tmp), TIMEOUT_MIX_CONNECTION_ESTABLISHEMENT)) != E_SUCCESS)
00352     {
00353       if (ret != E_UNKNOWN)
00354       {
00355         CAMsg::printMsg(LOG_CRIT,"Error receiving symmetric key info length! Reason: '%s' (%i)\n",
00356           GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00357       }
00358       else
00359       {
00360         CAMsg::printMsg(LOG_CRIT,"Error receiving symmetric key info length!\n");
00361       }
00362       return ret;
00363     }
00364     len = ntohl(tmp);
00365     
00366     if (len > 100000)
00367     {
00368       CAMsg::printMsg(LOG_WARNING,"Unrealistic length for key info: %u We might not be able to get a connection.\n",len);
00369     }
00370     
00371     messageBuff=new UINT8[len+1]; //+1 for the closing Zero
00372     CAMsg::printMsg(LOG_INFO,"Waiting for symmetric key from previous Mix with length %i...\n", len);
00373     if((ret = m_pMuxIn->receiveFully(messageBuff, len, TIMEOUT_MIX_CONNECTION_ESTABLISHEMENT)) != E_SUCCESS)
00374     {
00375       if (ret != E_UNKNOWN)
00376       {
00377         CAMsg::printMsg(LOG_ERR,"Socket error occurred while receiving the symmetric key from the previous mix! Reason: '%s' (%i) The previous mix might be unable to verify our Mix certificate(s) and therefore closed the connection. Please ask the operator for the log, and exchange your certificates if necessary.\n",
00378             GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00379       }
00380       else
00381       {
00382         CAMsg::printMsg(LOG_ERR,"Socket error occurred while receiving the symmetric key from the previous mix! The previous mix might be unable to verify our Mix certificate(s) and therefore closed the connection. Please ask the operator for the log, and exchange your certificates if necessary.\n");
00383       }
00384       delete []messageBuff;
00385       messageBuff = NULL;
00386       return ret;
00387     }
00388     messageBuff[len]=0;
00389     CAMsg::printMsg(LOG_INFO,"Symmetric Key Info received from previous mix is:\n");
00390     CAMsg::printMsg(LOG_INFO,"%s\n",(char*)messageBuff);
00391     //get document
00392     doc=parseDOMDocument(messageBuff,len);
00393     if(doc == NULL)
00394     {
00395       CAMsg::printMsg(LOG_CRIT,"Could not parse symmetric key of the previous mix!\n");
00396       delete []messageBuff;
00397       messageBuff = NULL;
00398       return E_UNKNOWN;
00399     }
00400     DOMElement* elemRoot=doc->getDocumentElement();
00401     if(elemRoot == NULL)
00402     {
00403       CAMsg::printMsg(LOG_CRIT,"Symmetric key XML structure of previous mix is invalid!\n");
00404       delete []messageBuff;
00405       messageBuff = NULL;
00406       if (doc != NULL)
00407       {
00408         doc->release();
00409         doc = NULL;
00410       }
00411       return E_UNKNOWN;
00412     }
00413     //verify certificate from previous mix if enabled
00414     if(CALibProxytest::getOptions()->verifyMixCertificates())
00415     {
00416       CACertificate* prevMixCert = CALibProxytest::getOptions()->getTrustedCertificateStore()->verifyMixCert(elemRoot);
00417       if(prevMixCert != NULL)
00418       {
00419         CAMsg::printMsg(LOG_DEBUG, "Previous mix certificate was verified by a trusted root CA.\n");
00420         CALibProxytest::getOptions()->setPrevMixTestCertificate(prevMixCert);
00421       }
00422       else
00423       {
00424         CAMsg::printMsg(LOG_ERR, "Could not verify certificate received from previous mix!\n");
00425         return E_UNKNOWN;
00426       }
00427     }
00428     //verify signature
00429     //CASignature oSig;
00430     CACertificate* pCert=CALibProxytest::getOptions()->getPrevMixTestCertificate();
00431     SINT32 result = CAMultiSignature::verifyXML(messageBuff, len, pCert);
00432     //oSig.setVerifyKey(pCert);
00433     delete pCert;
00434     pCert = NULL;
00435     //if(oSig.verifyXML(messageBuff,len)!=E_SUCCESS)
00436     if(result != E_SUCCESS)
00437     {
00438       CAMsg::printMsg(LOG_CRIT,"Could not verify the symmetric key!\n");
00439       delete []messageBuff;
00440       messageBuff = NULL;
00441       return E_UNKNOWN;
00442     }
00443 
00444      if ((result = checkCompatibility(elemRoot, "previous")) != E_SUCCESS)
00445     {
00446       delete []messageBuff;
00447       messageBuff = NULL;
00448       if (doc != NULL)
00449       {
00450         doc->release();
00451         doc = NULL;
00452       }
00453       return result;
00454     }
00455 
00456 
00457     elemNonce=NULL;
00458     getDOMChildByName(elemRoot,"Nonce",elemNonce,false);
00459     tmpLen=50;
00460     memset(tmpBuff,0,tmpLen);
00461     if(elemNonce==NULL||getDOMElementValue(elemNonce,tmpBuff,&tmpLen)!=E_SUCCESS||
00462       CABase64::decode(tmpBuff,tmpLen,tmpBuff,&tmpLen)!=E_SUCCESS||
00463       tmpLen!=SHA_DIGEST_LENGTH ||
00464       memcmp(SHA1(arNonce,16,NULL),tmpBuff,SHA_DIGEST_LENGTH)!=0
00465       )
00466     {
00467       CAMsg::printMsg(LOG_CRIT,"Could not verify the nonce from previous mix!\n");
00468       delete []messageBuff;
00469       messageBuff = NULL;
00470       if (doc != NULL)
00471       {
00472         doc->release();
00473         doc = NULL;
00474       }
00475       return E_UNKNOWN;
00476     }
00477     CAMsg::printMsg(LOG_INFO,"Verified the symmetric key from previous mix!\n");
00478 
00479     UINT8 key[150];
00480     UINT32 keySize=150;
00481     ret=decodeXMLEncryptedKey(key,&keySize,messageBuff,len,m_pRSA);
00482     delete []messageBuff;
00483     messageBuff = NULL;
00484     if(ret!=E_SUCCESS||keySize!=64)
00485     {
00486       CAMsg::printMsg(LOG_CRIT,"Could not decrypt the symmetric key from previous mix!\n");
00487       if (doc != NULL)
00488       {
00489         doc->release();
00490         doc = NULL;
00491       }
00492       return E_UNKNOWN;
00493     }
00494     if(m_pMuxIn->setReceiveKey(key,32)!=E_SUCCESS||m_pMuxIn->setSendKey(key+32,32)!=E_SUCCESS)
00495     {
00496       CAMsg::printMsg(LOG_CRIT,"Could not set the symmetric key to be used by the MuxSocket!\n");
00497       if (doc != NULL)
00498       {
00499         doc->release();
00500         doc = NULL;
00501       }
00502       return E_UNKNOWN;
00503     }
00504     m_pMuxIn->setCrypt(true);
00506     elemKeepAlive=NULL;
00507     elemKeepAliveSendInterval=NULL;
00508     elemKeepAliveRecvInterval=NULL;
00509     getDOMChildByName(elemRoot,"KeepAlive",elemKeepAlive);
00510     getDOMChildByName(elemKeepAlive,"SendInterval",elemKeepAliveSendInterval);
00511     getDOMChildByName(elemKeepAlive,"ReceiveInterval",elemKeepAliveRecvInterval);
00512     UINT32 tmpSendInterval,tmpRecvInterval;
00513     getDOMElementValue(elemKeepAliveSendInterval,tmpSendInterval,0xFFFFFFFF); //if now send interval was given set it to "infinite"
00514     getDOMElementValue(elemKeepAliveRecvInterval,tmpRecvInterval,0xFFFFFFFF); //if no recv interval was given --> set it to "infinite"
00515     CAMsg::printMsg(LOG_DEBUG,"KeepAlive-Traffic: Getting offer -- SendInterval %u -- Receive Interval %u\n",tmpSendInterval,tmpRecvInterval);
00516     m_u32KeepAliveSendInterval = u32KeepAliveSendInterval;
00517     if (m_u32KeepAliveSendInterval > tmpRecvInterval - 10000)
00518       m_u32KeepAliveSendInterval-=10000; //make the send interval a little bit smaller than the related receive interval
00519     m_u32KeepAliveRecvInterval=max(u32KeepAliveRecvInterval,tmpSendInterval);
00520     if (m_u32KeepAliveRecvInterval - 10000 < tmpSendInterval)
00521     {
00522       m_u32KeepAliveRecvInterval += 10000;
00523     }
00524     CAMsg::printMsg(LOG_DEBUG,"KeepAlive-Traffic: Calculated -- SendInterval %u -- Receive Interval %u\n",m_u32KeepAliveSendInterval,m_u32KeepAliveRecvInterval);
00525 
00526     if (doc != NULL)
00527     {
00528       doc->release();
00529       doc = NULL;
00530     }
00531 
00532     return E_SUCCESS;
00533   }
00534 
00535 #ifdef NEW_MIX_TYPE // TypeB mixes
00536   void CALastMix::reconfigureMix() {
00537   }
00538 #endif
00539 
00540 SINT32 CALastMix::reconfigure()
00541   {
00542     CAMsg::printMsg(LOG_DEBUG,"Reconfiguring Last Mix\n");
00543     CAMsg::printMsg(LOG_DEBUG,"Re-read cache proxies\n");
00544     if(setTargets()!=E_SUCCESS)
00545       CAMsg::printMsg(LOG_DEBUG,"Could not set new cache proxies\n");
00546     #ifndef NEW_MIX_TYPE // not TypeB mixes
00547       #if defined (DELAY_CHANNELS)||defined (DELAY_CHANNELS_LATENCY)
00548     CAMsg::printMsg(LOG_DEBUG,"Set new resources limitation parameters\n");
00549         if(m_pChannelList!=NULL) {
00550     #if defined (DELAY_CHANNELS)
00551       m_pChannelList->setDelayParameters( CALibProxytest::getOptions()->getDelayChannelUnlimitTraffic(),
00552                                           CALibProxytest::getOptions()->getDelayChannelBucketGrow(),
00553                                           CALibProxytest::getOptions()->getDelayChannelBucketGrowIntervall());
00554     #endif
00555     #if defined (DELAY_CHANNELS_LATENCY)
00556       UINT32 utemp=CALibProxytest::getOptions()->getDelayChannelLatency();
00557       m_pChannelList->setDelayLatencyParameters(  utemp);
00558     #endif
00559     }
00560       #endif
00561     #else // TypeB mixes
00562       reconfigureMix();
00563     #endif
00564     return E_SUCCESS;
00565   }
00566 
00567 THREAD_RETURN lm_loopLog(void* param)
00568   {
00569     CALastMix* pLastMix=(CALastMix*)param;
00570     pLastMix->m_bRunLog=true;
00571     UINT32 countLog=0;
00572     UINT8 buff[256];
00573     while(pLastMix->m_bRunLog)
00574       {
00575         if((countLog%10)==0)
00576           {
00577             logMemoryUsage();
00578           }
00579         if(countLog==0)
00580           {
00581             CAMsg::printMsg(LOG_DEBUG,"Uploaded  Packets: %u\n",pLastMix->m_logUploadedPackets);
00582             CAMsg::printMsg(LOG_DEBUG,"Downloaded Packets: %u\n",pLastMix->m_logDownloadedPackets);
00583             print64(buff,(UINT64&)pLastMix->m_logUploadedBytes);
00584             CAMsg::printMsg(LOG_DEBUG,"Uploaded  Bytes  : %s\n",buff);
00585             print64(buff,(UINT64&)pLastMix->m_logDownloadedBytes);
00586             CAMsg::printMsg(LOG_DEBUG,"Downloaded Bytes  : %s\n",buff);
00587             countLog=30;
00588           }
00589         sSleep(30);
00590         countLog--;
00591       }
00592     THREAD_RETURN_SUCCESS;
00593   }
00594 
00600 THREAD_RETURN lm_loopSendToMix(void* param)
00601   {
00602     CALastMix* pLastMix=(CALastMix*)param;
00603     CAQueue* pQueue=pLastMix->m_pQueueSendToMix;
00604     CAMuxSocket* pMuxSocket=pLastMix->m_pMuxIn;
00605     SINT32 ret;
00606     UINT32 len;
00607     UINT32 u32KeepAliveSendInterval=pLastMix->m_u32KeepAliveSendInterval;
00608 #ifndef USE_POOL
00609     tQueueEntry* pQueueEntry=new tQueueEntry;
00610     MIXPACKET* pMixPacket=&pQueueEntry->packet;
00611 
00612     while(!pLastMix->m_bRestart)
00613       {
00614         len=sizeof(tQueueEntry);
00615         ret=pQueue->getOrWait((UINT8*)pQueueEntry,&len,u32KeepAliveSendInterval);
00616         if(ret==E_TIMEDOUT)
00617           {
00618             pMixPacket->flags=CHANNEL_DUMMY;
00619             pMixPacket->channel=DUMMY_CHANNEL;
00620             getRandom(pMixPacket->data,DATA_SIZE);
00621           }
00622         else if(ret!=E_SUCCESS||len!=sizeof(tQueueEntry))
00623           {
00624             CAMsg::printMsg(LOG_ERR,"CALastMix::lm_loopSendToMix - Error in dequeueing MixPaket\n");
00625             CAMsg::printMsg(LOG_ERR,"ret=%i len=%i\n",ret,len);
00626             MONITORING_FIRE_NET_EVENT(ev_net_prevConnectionClosed);
00627             break;
00628           }
00629         if(pMuxSocket->send(pMixPacket)!=MIXPACKET_SIZE)
00630           {
00631             CAMsg::printMsg(LOG_ERR,"CALastMix::lm_loopSendToMix - Error in sending MixPaket\n");
00632             MONITORING_FIRE_NET_EVENT(ev_net_prevConnectionClosed);
00633             break;
00634           }
00635 #ifdef LOG_PACKET_TIMES
00636         if(!isZero64(pQueueEntry->timestamp_proccessing_start))
00637           {
00638             getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end);
00639             pLastMix->m_pLogPacketStats->addToTimeingStats(*pQueueEntry,CHANNEL_DATA,false);
00640           }
00641 #endif
00642       }
00643     delete pQueueEntry;
00644     pQueueEntry = NULL;
00645 #else
00646     CAPool* pPool=new CAPool(MIX_POOL_SIZE);
00647     tPoolEntry* pPoolEntry=new tPoolEntry;
00648     MIXPACKET* pMixPacket=&pPoolEntry->packet;
00649     while(!pLastMix->m_bRestart)
00650       {
00651         len=sizeof(tQueueEntry);
00652         SINT32 ret=pQueue->getOrWait((UINT8*)pPoolEntry,&len,MIX_POOL_TIMEOUT);
00653         if(ret==E_TIMEDOUT)
00654           {
00655             pMixPacket->flags=CHANNEL_DUMMY;
00656             pMixPacket->channel=DUMMY_CHANNEL;
00657             getRandom(pMixPacket->data,DATA_SIZE);
00658             #ifdef LOG_PACKET_TIMES
00659               setZero64(pPoolEntry->timestamp_proccessing_start);
00660             #endif
00661           }
00662         else if(ret!=E_SUCCESS||len!=sizeof(tQueueEntry))
00663           {
00664             break;
00665           }
00666         #ifdef LOG_PACKET_TIMES
00667           getcurrentTimeMicros(pPoolEntry->pool_timestamp_in);
00668         #endif
00669         pPool->pool(pPoolEntry);
00670         #ifdef LOG_PACKET_TIMES
00671           getcurrentTimeMicros(pPoolEntry->pool_timestamp_out);
00672         #endif
00673         if(pMuxSocket->send(pMixPacket)!=MIXPACKET_SIZE)
00674           break;
00675 #ifdef LOG_PACKET_TIMES
00676         if(!isZero64(pPoolEntry->timestamp_proccessing_start))
00677           {
00678             getcurrentTimeMicros(pPoolEntry->timestamp_proccessing_end);
00679             pLastMix->m_pLogPacketStats->addToTimeingStats(*pPoolEntry,CHANNEL_DATA,false);
00680           }
00681 #endif
00682       }
00683     delete pPoolEntry;
00684     pPoolEntry = NULL;
00685     delete pPool;
00686     pPool = NULL;
00687 #endif
00688     CAMsg::printMsg(LOG_DEBUG,"Exiting Thread SendToMix\n");
00689     THREAD_RETURN_SUCCESS;
00690   }
00691 
00692 
00693 /* How to end this thread:
00694  * 1. set m_brestart=true
00695  */
00696 THREAD_RETURN lm_loopReadFromMix(void *pParam)
00697   {
00698     CALastMix* pLastMix=(CALastMix*)pParam;
00699     CAMuxSocket* pMuxSocket=pLastMix->m_pMuxIn;
00700     CAQueue* pQueue=pLastMix->m_pQueueReadFromMix;
00701     tQueueEntry* pQueueEntry=new tQueueEntry;
00702     MIXPACKET* pMixPacket=&pQueueEntry->packet;
00703     CASingleSocketGroup* pSocketGroup=new CASingleSocketGroup(false);
00704     pSocketGroup->add(*pMuxSocket);
00705     #ifdef USE_POOL
00706       CAPool* pPool=new CAPool(MIX_POOL_SIZE);
00707     #endif
00708     UINT64 keepaliveNow,keepaliveLast;
00709     UINT32 u32KeepAliveRecvInterval=pLastMix->m_u32KeepAliveRecvInterval;
00710     getcurrentTimeMillis(keepaliveLast);
00711     while(!pLastMix->m_bRestart)
00712       {
00713         if(pQueue->getSize()>MAX_READ_FROM_PREV_MIX_QUEUE_SIZE)
00714           {
00715 #ifdef DEBUG
00716             CAMsg::printMsg(LOG_DEBUG,"CAFirstMix::Queue is full!\n");
00717 #endif
00718             msSleep(200);
00719             getcurrentTimeMillis(keepaliveLast);
00720             continue;
00721           }
00722         //check if the connection is broken because we did not receive a Keep_alive-Message
00723         getcurrentTimeMillis(keepaliveNow);
00724         UINT32 keepaliveDiff=diff64(keepaliveNow,keepaliveLast);
00725         if(keepaliveDiff>u32KeepAliveRecvInterval)
00726           {
00727             CAMsg::printMsg(LOG_ERR,"CALastMix::loopReadFromMix() -- restart because of KeepAlive-Traffic Timeout!\n");
00728             pLastMix->m_bRestart=true;
00729             MONITORING_FIRE_NET_EVENT(ev_net_prevConnectionClosed);
00730             break;
00731           }
00732         SINT32 ret=pSocketGroup->select(MIX_POOL_TIMEOUT);
00733         if(ret < 0)
00734           {
00735             if (ret == E_TIMEDOUT)
00736               {
00737                 #ifdef USE_POOL
00738                   pMixPacket->flags=CHANNEL_DUMMY;
00739                   pMixPacket->channel=DUMMY_CHANNEL;
00740                   getRandom(pMixPacket->data,DATA_SIZE);
00741                   #ifdef LOG_PACKET_TIMES
00742                     setZero64(pQueueEntry->timestamp_proccessing_start);
00743                   #endif
00744                 #else
00745                   continue;
00746                 #endif
00747               }
00748             else
00749               {
00750                 /* another error occured (happens sometimes while debugging because
00751                  * of interruption, if a breakpoint is reached -> poll() returns
00752                  * errorcode EINTR)
00753                  * Note: Any Error on select() does not mean, that the underliny connections have some error state, because
00754                  * in this case select() returns the socket and than this socket returns the error
00755                  */
00756                 continue;
00757               }
00758           }
00759         else if(ret>0)
00760         {
00761           ret=pMuxSocket->receive(pMixPacket); //receives a whole MixPacket
00762           #ifdef LOG_PACKET_TIMES
00763             getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_start);
00764           #endif
00765           #ifdef DATA_RETENTION_LOG
00766             pQueueEntry->dataRetentionLogEntry.t_in=htonl(time(NULL));
00767           #endif
00768           if(ret!=MIXPACKET_SIZE)
00769           {//something goes wrong...
00770             CAMsg::printMsg(LOG_ERR,"CALastMix::lm_loopReadFromMix - received returned: %i\n",ret);
00771             pLastMix->m_bRestart=true;
00772             MONITORING_FIRE_NET_EVENT(ev_net_prevConnectionClosed);
00773             break;
00774           }
00775         }
00776     #ifdef USE_POOL
00777       #ifdef LOG_PACKET_TIMES
00778         getcurrentTimeMicros(pQueueEntry->pool_timestamp_in);
00779       #endif
00780         pPool->pool((tPoolEntry*) pQueueEntry);
00781       #ifdef LOG_PACKET_TIMES
00782         getcurrentTimeMicros(pQueueEntry->pool_timestamp_out);
00783       #endif
00784     #endif
00785         pQueue->add(pQueueEntry,sizeof(tQueueEntry));
00786         getcurrentTimeMillis(keepaliveLast);
00787       }
00788     delete pQueueEntry;
00789     pQueueEntry = NULL;
00790     delete pSocketGroup;
00791     pSocketGroup = NULL;
00792     #ifdef USE_POOL
00793       delete pPool;
00794       pPool = NULL;
00795     #endif
00796     THREAD_RETURN_SUCCESS;
00797   }
00798 
00799 #ifdef LOG_CRIME
00800 //Assuming we have aligned HTTP or SOCKS protocolData
00801   UINT8* CALastMix::parseDomainFromPayload(const UINT8 *payloadData, UINT32 payloadDataLength)
00802   {
00803     if( (payloadDataLength < 5) ||
00804       (payloadDataLength > PAYLOAD_SIZE) )
00805     {
00806       return NULL;
00807     }
00808 
00809     if( (payloadData[0] == 0x05) && (payloadData[1] & 0x03) )
00810     {
00811       //in this case we have a SOCKS message
00812       UINT32 tempUrlLength = 0, urlStartOffset = 0;
00813       //of which address type is the dst address?
00814       switch(payloadData[3])
00815       {
00816         case 0x01: //IPv4_Address
00817         {
00818           tempUrlLength = 4;
00819           urlStartOffset = 4;
00820           break;
00821         }
00822 
00823         case 0x03: //Domain name
00824         {
00825           tempUrlLength = payloadData[4];
00826           urlStartOffset = 5;
00827           //CAMsg::printMsg(LOG_ERR,"SOCKS v5 domain name length %u.\n", tempUrlLength);
00828           break;
00829         }
00830 
00831         case 0x4: //IPv6 address
00832         {
00833           tempUrlLength = 16;
00834           urlStartOffset = 4;
00835           break;
00836         }
00837 
00838         default:
00839         {
00840           return NULL;
00841         }
00842       }
00843       if(payloadDataLength < (urlStartOffset + tempUrlLength) )
00844       {
00845         return NULL;
00846       }
00847       UINT8 *address = new UINT8[tempUrlLength+1];
00848       memcpy(address, payloadData+urlStartOffset, tempUrlLength);
00849       address[tempUrlLength] = 0;
00850       //CAMsg::printMsg(LOG_ERR,"SOCKS v5 found with address %s.\n", address);
00851       return address;
00852     }
00853     else
00854     {
00855       //In this case the message is handled as a common HTTP request
00856       //So we lock for the Request-Line
00857       //Note according to [HTTP 1.1] the Request-Line might be preceded by CRLF
00858       //Snip: In the interest of robustness, servers SHOULD ignore any empty
00859       //      line(s) received where a Request-Line is expected. In other words, if
00860       //      the server is reading the protocol stream at the beginning of a
00861       //      message and receives a CRLF first, it should ignore the CRLF.
00862 
00863       //OK lets try to use a regular expression for the task instead of a hand crafted parser...
00864       //do the match...
00865       regmatch_t theMatches[3];
00866       int ret=regnexec(m_pregexpRequestLine,(const char*)payloadData,payloadDataLength,3,theMatches,0);
00867       if(ret!=0)
00868         return NULL;
00869 
00870       const UINT8* httpVerb=payloadData+theMatches[1].rm_so;
00871       UINT8* domainName=NULL;
00872       if((payloadData+theMatches[1].rm_eo-payloadData+theMatches[1].rm_so)>6 && memcmp("CONNECT",httpVerb,7)==0)
00873         {//Connect request --> URI is domain [:port]
00874           UINT32 matchLen=theMatches[2].rm_eo-theMatches[2].rm_so;
00875           domainName=new UINT8[matchLen+1];
00876           memcpy(domainName,payloadData+theMatches[2].rm_so,matchLen);
00877           domainName[matchLen]=0;
00878           strtok((char*)domainName,":");
00879         }
00880       else
00881         {
00882           //do the match...
00883           regmatch_t theDomainMatches[2];
00884           ret=regnexec(m_pregexpDomainOfURI,(const char*)payloadData+theMatches[2].rm_so,theMatches[2].rm_eo-theMatches[2].rm_so,2,theDomainMatches,0);
00885           if(ret!=0)
00886             return NULL;
00887           UINT32 matchLen=theDomainMatches[1].rm_eo-theDomainMatches[1].rm_so;
00888           domainName=new UINT8[matchLen+1];
00889           memcpy(domainName,payloadData+theMatches[2].rm_so+theDomainMatches[1].rm_so,matchLen);
00890           domainName[matchLen]=0;
00891         }
00892       return domainName;
00893     }
00894   }
00895 
00896   bool CALastMix::checkCrime(const UINT8* payLoad,UINT32 payLen,bool bURLCheck)
00897   {
00898     //Lots of TODO!!!!
00899     //DNS Lookup may block if Host does not exists!!!!!
00900     //so we use regexp....
00901     if(bURLCheck)
00902       {
00903         UINT8 *startOfUrl = parseDomainFromPayload(payLoad, payLen);
00904         if(startOfUrl!=NULL)
00905           {
00906             UINT32 strLen = strlen((char *)startOfUrl);
00907             for(UINT32 i = 0; i < m_nCrimeRegExpsURL; i++)
00908             {
00909               if(regnexec(&m_pCrimeRegExpsURL[i],(char*)startOfUrl,strLen,0,NULL,0)==0)
00910               {
00911                 delete [] startOfUrl;
00912                 return true;
00913               }
00914             }
00915             delete [] startOfUrl;
00916           }
00917       }
00918     for(UINT32 i = 0; i < m_nCrimeRegExpsPayload; i++)
00919     {
00920       if (regnexec(&m_pCrimeRegExpsPayload[i],(const char*)payLoad ,payLen,0,NULL,0)==0)
00921       {
00922         return true;
00923       }
00924     }
00925     return false;
00926   }
00927 #endif
00928 
00933 SINT32 CALastMix::setTargets()
00934   {
00935     UINT32 cntTargets=CALibProxytest::getOptions()->getTargetInterfaceCount();
00936     if(cntTargets==0)
00937       {
00938         CAMsg::printMsg(LOG_CRIT,"No Targets (proxies) specified!\n");
00939         return E_UNKNOWN;
00940       }
00941     m_pCacheLB->clean();
00942     m_pSocksLB->clean();
00943     UINT32 i;
00944     for(i=1;i<=cntTargets;i++)
00945       {
00946         CATargetInterface oTargetInterface;
00947         CALibProxytest::getOptions()->getTargetInterface(oTargetInterface,i);
00948         if(oTargetInterface.getTargetType()==TARGET_HTTP_PROXY)
00949         {
00950           m_pCacheLB->add(oTargetInterface.getAddr());
00951         }
00952         else if(oTargetInterface.getTargetType()==TARGET_SOCKS_PROXY)
00953         {
00954           m_pSocksLB->add(oTargetInterface.getAddr());
00955         }
00956         oTargetInterface.cleanAddr();
00957       }
00958     CAMsg::printMsg(LOG_DEBUG,"This mix will use the following proxies:\n");
00959     for(i=0;i<m_pCacheLB->getElementCount();i++)
00960     {
00961       CASocketAddrINet* pAddr=m_pCacheLB->get();
00962       UINT8 ip[4];
00963       pAddr->getIP(ip);
00964       UINT32 port=pAddr->getPort();
00965       CAMsg::printMsg(LOG_DEBUG,"%u. HTTP Proxy's Address: %u.%u.%u.%u:%u\n",i+1,ip[0],ip[1],ip[2],ip[3],port);
00966     }
00967     for(i=0;i<m_pSocksLB->getElementCount();i++)
00968       {
00969         CASocketAddrINet* pAddr=m_pSocksLB->get();
00970         UINT8 ip[4];
00971         pAddr->getIP(ip);
00972         UINT32 port=pAddr->getPort();
00973         CAMsg::printMsg(LOG_DEBUG,"%u. SOCKS Proxy's Address: %u.%u.%u.%u:%u\n",i+1,ip[0],ip[1],ip[2],ip[3],port);
00974       }
00975 
00976 
00977     return E_SUCCESS;
00978   }
00979 
00980 SINT32 CALastMix::clean()
00981 {
00982     m_bRestart=true;
00983     MONITORING_FIRE_NET_EVENT(ev_net_prevConnectionClosed);
00984     m_bRunLog=false;
00985 #ifdef REPLAY_DETECTION
00986     if(m_pReplayMsgProc!=NULL)
00987       {
00988         delete m_pReplayMsgProc;
00989         m_pReplayMsgProc = NULL;
00990       }
00991     m_pReplayMsgProc=NULL;
00992 #endif
00993 
00994     if(m_pMuxInControlChannelDispatcher!=NULL)
00995       {
00996         delete m_pMuxInControlChannelDispatcher;
00997         m_pMuxInControlChannelDispatcher = NULL;
00998       }
00999     m_pMuxInControlChannelDispatcher=NULL;
01000 
01001     if(m_pMuxIn!=NULL)
01002       {
01003         m_pMuxIn->close();
01004       }
01005     //writng some bytes to the queue...
01006     if(m_pQueueSendToMix!=NULL)
01007       {
01008         UINT8 b[sizeof(tQueueEntry)+1];
01009         m_pQueueSendToMix->add(b,sizeof(tQueueEntry)+1);
01010       }
01011 
01012     if(m_pthreadSendToMix!=NULL)
01013       {
01014         CAMsg::printMsg(LOG_CRIT,"Wait for LoopSendToMix!\n");
01015         m_pthreadSendToMix->join();
01016         delete m_pthreadSendToMix;
01017         m_pthreadSendToMix = NULL;
01018       }
01019     m_pthreadSendToMix=NULL;
01020     if(m_pthreadReadFromMix!=NULL)
01021       {
01022         CAMsg::printMsg(LOG_CRIT,"Wait for LoopReadFromMix!\n");
01023         m_pthreadReadFromMix->join();
01024         delete m_pthreadReadFromMix;
01025         m_pthreadReadFromMix = NULL;
01026       }
01027     m_pthreadReadFromMix=NULL;
01028 
01029 #ifdef LOG_PACKET_TIMES
01030       CAMsg::printMsg(LOG_CRIT,"Wait for LoopLogPacketStats to terminate!\n");
01031       if(m_pLogPacketStats!=NULL)
01032         {
01033           m_pLogPacketStats->stop();
01034           delete m_pLogPacketStats;
01035           m_pLogPacketStats = NULL;
01036         }
01037       m_pLogPacketStats=NULL;
01038 #endif
01039     if(m_pChannelList!=NULL)
01040       {
01041         lmChannelListEntry* pChannelListEntry=m_pChannelList->getFirstSocket();
01042         while(pChannelListEntry!=NULL)
01043           {
01044             delete pChannelListEntry->pCipher;
01045             pChannelListEntry->pCipher = NULL;
01046             delete pChannelListEntry->pQueueSend;
01047             pChannelListEntry->pQueueSend = NULL;
01048             if (pChannelListEntry->pSocket != NULL)
01049             {
01050               pChannelListEntry->pSocket->close();
01051               delete pChannelListEntry->pSocket;
01052               pChannelListEntry->pSocket = NULL;
01053             }
01054             pChannelListEntry=m_pChannelList->getNextSocket();
01055           }
01056       }
01057     delete m_pQueueReadFromMix;
01058     m_pQueueReadFromMix = NULL;
01059     delete m_pQueueSendToMix;
01060     m_pQueueSendToMix = NULL;
01061     #ifndef NEW_MIX_TYPE // not TypeB mixes
01062       /* TypeB mixes are using an own implementation */
01063     delete m_pChannelList;
01064     m_pChannelList = NULL;
01065     if(m_pMuxIn != NULL)
01066     {
01067       m_pMuxIn->close();
01068       delete m_pMuxIn;
01069       m_pMuxIn=NULL;
01070     }
01071 
01072     delete m_pRSA;
01073     m_pRSA = NULL;
01074     #endif
01075     return E_SUCCESS;
01076   }
01077 
01078 SINT32 CALastMix::initMixCascadeInfo(DOMElement*  mixes)
01079 {
01080     SINT32 r = CAMix::initMixCascadeInfo(mixes);
01081     DOMElement* cascade = m_docMixCascadeInfo->getDocumentElement();
01082     setDOMElementAttribute(cascade,"create",(UINT8*)"true");
01083     return r;
01084 }
01085 #endif //ONLY_LOCAL_PROXY