Mixe for Privacy and Anonymity in the Internet
CAFirstMix.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 "CAFirstMix.hpp"
00031 #include "CASocketGroup.hpp"
00032 #include "CASingleSocketGroup.hpp"
00033 #include "CAMsg.hpp"
00034 #include "CACmdLnOptions.hpp"
00035 #include "CAFirstMixChannelList.hpp"
00036 #include "CAListenerInterface.hpp"
00037 #include "CAASymCipher.hpp"
00038 #include "CAInfoService.hpp"
00039 #include "CASocketAddrINet.hpp"
00040 #include "CATempIPBlockList.hpp"
00041 #ifdef HAVE_UNIX_DOMAIN_PROTOCOL
00042   #include "CASocketAddrUnix.hpp"
00043 #endif
00044 #include "CAThread.hpp"
00045 #include "CAUtil.hpp"
00046 #include "CASignature.hpp"
00047 #include "CABase64.hpp"
00048 #include "xml/DOM_Output.hpp"
00049 #include "CAPool.hpp"
00050 #ifdef WITH_CONTROL_CHANNELS_TEST
00051   #include "CAControlChannelTest.hpp"
00052 #endif
00053 #ifdef PAYMENT
00054   #include "CAAccountingControlChannel.hpp"
00055   #include "CAAccountingInstance.hpp"
00056   #include "CAAccountingDBInterface.hpp"
00057 #endif
00058 #include "CAReplayControlChannel.hpp"
00059 #include "CAStatusManager.hpp"
00060 #include "CALibProxytest.hpp"
00061 const UINT32 CAFirstMix::MAX_CONCURRENT_NEW_CONNECTIONS = NUM_LOGIN_WORKER_TRHEADS * 2;
00062 
00063 bool CAFirstMix::isShuttingDown()
00064 {
00065   return m_bIsShuttingDown;
00066 }
00067 
00068 SINT32 CAFirstMix::initOnce()
00069   {
00070     SINT32 ret=CAMix::initOnce();
00071     if(ret!=E_SUCCESS)
00072       return ret;
00073     CAMsg::printMsg(LOG_DEBUG,"Starting FirstMix InitOnce\n");
00074     /*m_pSignature=CALibProxytest::getOptions()->getSignKey();
00075     if(m_pSignature==NULL)*/
00076     m_pMultiSignature = CALibProxytest::getOptions()->getMultiSigner();
00077     if(m_pMultiSignature == NULL)
00078       return E_UNKNOWN;
00079     //Try to find out how many (real) ListenerInterfaces are specified
00080     UINT32 tmpSocketsIn=CALibProxytest::getOptions()->getListenerInterfaceCount();
00081     m_nSocketsIn=0;
00082     for(UINT32 i=1;i<=tmpSocketsIn;i++)
00083     {
00084       CAListenerInterface* pListener=NULL;
00085       pListener=CALibProxytest::getOptions()->getListenerInterface(i);
00086       if(pListener==NULL)
00087         continue;
00088       if(!pListener->isVirtual())
00089       {
00090         m_nSocketsIn++;
00091       }
00092       delete pListener;
00093       pListener = NULL;
00094     }
00095     if(m_nSocketsIn<1)
00096     {
00097       CAMsg::printMsg(LOG_CRIT,"No usable ListenerInterfaces specified (maybe wrong values or all are 'virtual'!\n");
00098       return E_UNKNOWN;
00099     }
00100 
00101     CAMsg::printMsg(LOG_DEBUG,"Starting FirstMix InitOnce - finished\n");
00102     return E_SUCCESS;
00103   }
00104 
00105 
00106 
00107 SINT32 CAFirstMix::init()
00108   {
00109     if (isShuttingDown())
00110     {
00111       return E_SHUTDOWN;
00112     }
00113 
00114 #ifdef DYNAMIC_MIX
00115     m_bBreakNeeded = m_bReconfigured;
00116 #endif
00117 
00118     CAMsg::printMsg(LOG_DEBUG,"Starting FirstMix Init\n");
00119     m_nMixedPackets=0; //reset to zero after each restart (at the moment neccessary for infoservice)
00120     m_bRestart=false;
00121     //Establishing all Listeners
00122     UINT32 i;
00123     m_arrSocketsIn=new CASocket*[m_nSocketsIn];
00124     for (i = 0; i < m_nSocketsIn; i++)
00125     {
00126       m_arrSocketsIn[i] = NULL;
00127     }
00128     //initiate ownerDocument for tc templates
00129     m_templatesOwner = createDOMDocument();
00130 
00131     SINT32 retSockets = CALibProxytest::getOptions()->createSockets(true, m_arrSocketsIn, m_nSocketsIn);
00132 
00133 
00134     if (retSockets != E_SUCCESS)
00135     {
00136       return retSockets;
00137     }
00138 
00139     CASocketAddr* pAddrNext=NULL;
00140     for(i=0;i<CALibProxytest::getOptions()->getTargetInterfaceCount();i++)
00141       {
00142         CATargetInterface oNextMix;
00143         CALibProxytest::getOptions()->getTargetInterface(oNextMix,i+1);
00144         if(oNextMix.getTargetType()==TARGET_MIX)
00145         {
00146           pAddrNext=oNextMix.getAddr();
00147           break;
00148         }
00149         oNextMix.cleanAddr();
00150       }
00151     if(pAddrNext==NULL)
00152       {
00153         CAMsg::printMsg(LOG_CRIT,"No next Mix specified! Please insert the address of a next mix into your configuration.\n");
00154         return E_UNKNOWN;
00155       }
00156     m_pMuxOut=new CAMuxSocket();
00157     if(m_pMuxOut->getCASocket()->create(pAddrNext->getType())!=E_SUCCESS)
00158       {
00159         CAMsg::printMsg(LOG_CRIT,
00160           "Cannot create SOCKET for connection to next Mix! Please check if the network and socket settings in your system are correct.\n");
00161         return E_UNKNOWN;
00162       }
00163     m_pMuxOut->getCASocket()->setSendBuff(500*MIXPACKET_SIZE);
00164     m_pMuxOut->getCASocket()->setRecvBuff(500*MIXPACKET_SIZE);
00165     //if(((*m_pMuxOut))->setSendLowWat(MIXPACKET_SIZE)!=E_SUCCESS)
00166     //  CAMsg::printMsg(LOG_INFO,"SOCKET Option SENDLOWWAT not set!\n");
00167     CAMsg::printMsg(LOG_INFO,"MUXOUT-SOCKET RecvBuffSize: %i\n",m_pMuxOut->getCASocket()->getRecvBuff());
00168     CAMsg::printMsg(LOG_INFO,"MUXOUT-SOCKET SendBuffSize: %i\n",m_pMuxOut->getCASocket()->getSendBuff());
00169     //CAMsg::printMsg(LOG_INFO,"MUXOUT-SOCKET SendLowWatSize: %i\n",((*m_pMuxOut))->getSendLowWat());
00170 
00172     if((retSockets = connectToNextMix(pAddrNext)) != E_SUCCESS)
00173     {
00174       delete pAddrNext;
00175       pAddrNext = NULL;
00176       CAMsg::printMsg(LOG_DEBUG, "CAFirstMix::init - Unable to connect to next mix. Reason: %s (%i)\n", GET_NET_ERROR_STR(retSockets), retSockets);       
00177       return E_UNKNOWN;
00178     }
00179     delete pAddrNext;
00180     pAddrNext = NULL;
00181     MONITORING_FIRE_NET_EVENT(ev_net_nextConnected);
00182     CAMsg::printMsg(LOG_INFO,"Established socket connection to next mix. Starting key exchange...\n");
00183     m_pMuxOut->getCASocket()->setKeepAlive((UINT32)1800);
00184 
00185 
00186     if(processKeyExchange()!=E_SUCCESS)
00187     {
00188       MONITORING_FIRE_NET_EVENT(ev_net_nextConnectionClosed);
00189       CAMsg::printMsg(LOG_CRIT,"Error in establishing secure communication with next Mix. Disconnecting...\n");
00190         return E_UNKNOWN;
00191     }
00192   else
00193   {
00194     CAMsg::printMsg(LOG_INFO,"Secure connection to next Mix was established successfully.\n");
00195   }
00196     m_pIPList=new CAIPList();
00197     m_pIPBlockList = new CATempIPBlockList(1000 * 60 * 2); 
00198 #ifdef COUNTRY_STATS
00199     char* db_host;
00200     char* db_user;
00201     char* db_passwd;
00202     CALibProxytest::getOptions()->getCountryStatsDBConnectionLoginData(&db_host,&db_user,&db_passwd);
00203     SINT32 retcountrydb=initCountryStats(db_host,db_user,db_passwd);
00204     delete[] db_host;
00205     db_host = NULL;
00206     delete[] db_user;
00207     db_user = NULL;
00208     delete[] db_passwd;
00209     db_passwd = NULL;
00210     if(retcountrydb!=E_SUCCESS)
00211       return E_UNKNOWN;
00212 #endif
00213     m_pQueueSendToMix=new CAQueue(sizeof(tQueueEntry));
00214     m_pQueueReadFromMix=new CAQueue(sizeof(tQueueEntry));
00215     m_pChannelList=new CAFirstMixChannelList();
00216 #ifdef HAVE_EPOLL
00217     m_psocketgroupUsersRead=new CASocketGroupEpoll(false);
00218     m_psocketgroupUsersWrite=new CASocketGroupEpoll(true);
00219 #else
00220     m_psocketgroupUsersRead=new CASocketGroup(false);
00221     m_psocketgroupUsersWrite=new CASocketGroup(true);
00222 #endif
00223 
00224     m_pMuxOutControlChannelDispatcher=new CAControlChannelDispatcher(m_pQueueSendToMix,NULL,NULL);
00225 #ifdef REPLAY_DETECTION
00226     m_pReplayDB=new CADatabase();
00227     m_pReplayDB->start();
00228     m_pReplayMsgProc=new CAReplayCtrlChannelMsgProc(this);
00229     m_u64ReferenceTime=time(NULL);
00230     m_u64LastTimestampReceived=time(NULL);
00231 #endif
00232 
00233 #ifdef PAYMENT
00234     if (CAAccountingDBInterface::init() != E_SUCCESS)
00235     {
00236       return E_UNKNOWN;
00237     }
00238     CAAccountingInstance::init(this);
00239 #endif
00240 
00241     m_pthreadsLogin=new CAThreadPool(NUM_LOGIN_WORKER_TRHEADS,MAX_LOGIN_QUEUE,false);
00242 
00243     //Starting thread for Step 1
00244     m_pthreadAcceptUsers=new CAThread((UINT8*)"CAFirstMix - AcceptUsers");
00245     m_pthreadAcceptUsers->setMainLoop(fm_loopAcceptUsers);
00246     m_pthreadAcceptUsers->start(this);
00247 
00248     //Starting thread for Step 3
00249     m_pthreadSendToMix=new CAThread((UINT8*)"CAFirstMix - SendToMix");
00250     m_pthreadSendToMix->setMainLoop(fm_loopSendToMix);
00251     m_pthreadSendToMix->start(this);
00252 
00253     //Startting thread for Step 4a
00254     m_pthreadReadFromMix=new CAThread((UINT8*)"CAFirstMix - ReadFromMix");
00255     m_pthreadReadFromMix->setMainLoop(fm_loopReadFromMix);
00256     m_pthreadReadFromMix->start(this);
00257 #ifdef CH_LOG_STUDY
00258     nrOfChThread = new CAThread((UINT8*)"CAFirstMix - Channel open logging thread");
00259     nrOfChThread->setMainLoop(fm_loopLogChannelsOpened);
00260     nrOfChThread->start(this);
00261     currentOpenedChannels = 0;
00262 #endif //CH_LOG_STUDY
00263     //Starting thread for logging
00264 #ifdef LOG_PACKET_TIMES
00265     m_pLogPacketStats=new CALogPacketStats();
00266     m_pLogPacketStats->setLogIntervallInMinutes(FM_PACKET_STATS_LOG_INTERVALL);
00267     m_pLogPacketStats->start();
00268 #endif
00269 #ifdef REPLAY_DETECTION
00270 //    sendReplayTimestampRequestsToAllMixes();
00271 #endif
00272     CAMsg::printMsg(LOG_DEBUG,"CAFirstMix init() succeeded\n");
00273     MONITORING_FIRE_NET_EVENT(ev_net_keyExchangeNextSuccessful);
00274     return E_SUCCESS;
00275 }
00276 
00277 SINT32 CAFirstMix::connectToNextMix(CASocketAddr* a_pAddrNext)
00278 {
00279   UINT8 buff[255];
00280   a_pAddrNext->toString(buff,255);
00281   CAMsg::printMsg(LOG_INFO,"Try to connect to next Mix on %s ...\n",buff);
00282   SINT32 err = E_UNKNOWN;
00283   SINT32 errLast = E_SUCCESS;
00284   
00285   for(UINT32 i=0; i < 100; i++)
00286   {
00287 #ifdef DYNAMIC_MIX
00288 
00289     if(m_bBreakNeeded != m_bReconfigured)
00290     {
00291       CAMsg::printMsg(LOG_DEBUG, "CAFirstMix::connectToNextMix - Broken the connect loop!\n");
00292       break;
00293     }
00294 #endif
00295     err = m_pMuxOut->connect(*a_pAddrNext);
00296     if(err != E_SUCCESS)
00297     {
00298       err=GET_NET_ERROR;
00299       
00300       if(err!=ERR_INTERN_TIMEDOUT&&err!=ERR_INTERN_CONNREFUSED)
00301       {
00302         CAMsg::printMsg(LOG_ERR, "Cannot connect to next Mix on %s. Reason: %s (%i)\n",
00303           buff, GET_NET_ERROR_STR(err), err);
00304         break;
00305       }
00306         
00307       if (errLast != err || i % 10 == 0)
00308       {
00309         CAMsg::printMsg(LOG_ERR, "Cannot connect to next Mix on %s. Reason: %s (%i). Retrying...\n",
00310           buff, GET_NET_ERROR_STR(err), err);
00311         errLast = err;
00312       }
00313       else
00314       {
00315 #ifdef _DEBUG
00316         CAMsg::printMsg(LOG_DEBUG,"Cannot connect... retrying\n");
00317 #endif
00318       }
00319       sSleep(10);
00320     }
00321     else
00322     {
00323       break;
00324     }
00325   }
00326   return err;
00327 }
00328 
00329 /*
00330 *@DOCME
00331 */
00332 SINT32 CAFirstMix::processKeyExchange()
00333   {
00334     UINT8* recvBuff=NULL;
00335     UINT32 len;
00336     SINT32 ret;
00337     CAMsg::printMsg(LOG_INFO, "Try to read the Key Info length from next Mix...\n");
00338     if((ret = m_pMuxOut->receiveFully((UINT8*) &len, sizeof(len), TIMEOUT_MIX_CONNECTION_ESTABLISHEMENT)) != E_SUCCESS)
00339       {
00340         if (ret != E_UNKNOWN)
00341           {
00342             CAMsg::printMsg(LOG_CRIT,"Error receiving Key Info length from next mix! Reason: '%s' (%i)\n",GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00343           }
00344         else
00345           {
00346             CAMsg::printMsg(LOG_CRIT,"Error receiving Key Info length from next mix!\n");
00347           }
00348         return ret;
00349       }
00350     len=ntohl(len);
00351     CAMsg::printMsg(LOG_INFO, "Received next mix Key Info length %u\n",len);
00352   
00353     if (len > 100000)
00354       {
00355         CAMsg::printMsg(LOG_WARNING,"Unrealistic length for key info: %u We might not be able to get a connection.\n",len);
00356       }
00357   
00358     recvBuff=new UINT8[len+1];
00359 
00360     if ((ret =m_pMuxOut->receiveFully(recvBuff, len, TIMEOUT_MIX_CONNECTION_ESTABLISHEMENT)) != E_SUCCESS)
00361       {
00362         if (ret != E_UNKNOWN)
00363           {
00364             CAMsg::printMsg(LOG_CRIT,"Error receiving Key Info from next mix! Reason: '%s' (%i)\n",GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00365           }
00366         else
00367           {
00368             CAMsg::printMsg(LOG_CRIT,"Error receiving Key Info from next mix!\n");
00369           }
00370         delete []recvBuff;
00371         recvBuff = NULL;
00372         return E_UNKNOWN;
00373       }
00374     recvBuff[len]=0;
00375     //get the Keys from the other mixes (and the Mix-Id's...!)
00376     CAMsg::printMsg(LOG_INFO,"Received Key Info from next mix...\n");
00377     CAMsg::printMsg(LOG_DEBUG,"%s\n",recvBuff);
00378 
00379     XERCES_CPP_NAMESPACE::DOMDocument* doc=parseDOMDocument(recvBuff, len);
00380     delete []recvBuff;
00381     recvBuff = NULL;
00382     DOMElement* elemMixes=doc->getDocumentElement();
00383     if(elemMixes == NULL)
00384     {
00385     if(doc != NULL)
00386     {
00387       doc->release();
00388       doc = NULL;
00389     }
00390     CAMsg::printMsg(LOG_INFO,"before returning...\n");
00391     return E_UNKNOWN;
00392     }
00393     SINT32 count=0;
00394     if(getDOMElementAttribute(elemMixes,"count",&count)!=E_SUCCESS)
00395     {
00396       if(doc != NULL)
00397     {
00398       doc->release();
00399       doc = NULL;
00400     }
00401         return E_UNKNOWN;
00402     }
00403  /*
00404     @todo Do not know why we do this here - probably it has something todo with the
00405     dynamic mix config, but makes not sense at all for me...
00406 
00407     getDOMElementAttribute(elemMixescascadeNaem
00408     char *cascadeName;
00409     cascadeName = elemMixes.getAttribute("cascadeName").transcode();
00410     if(cascadeName == NULL)
00411         return E_UNKNOWN;
00412     CALibProxytest::getOptions()->setCascadeName(cascadeName);
00413 */
00414     if(CALibProxytest::getOptions()->getTermsAndConditions() != NULL)
00415     {
00416       appendTermsAndConditionsExtension(doc, elemMixes);
00417     }
00418 
00419     SINT32 extRet = handleKeyInfoExtensions(elemMixes);
00420     if(extRet != E_SUCCESS)
00421     {
00422       if(doc != NULL)
00423     {
00424       doc->release();
00425       doc = NULL;
00426     }
00427     return E_UNKNOWN;
00428     }
00429     m_pRSA=new CAASymCipher;
00430 
00431 #ifdef EXPORT_ASYM_PRIVATE_KEY
00432     if(CALibProxytest::getOptions()->isImportKey())
00433       {
00434         UINT32 keyFileBuffLen=8096;
00435         UINT8* keyFileBuff=new UINT8[keyFileBuffLen];
00436         CALibProxytest::getOptions()->getEncryptionKeyImportFile(keyFileBuff,keyFileBuffLen);
00437         UINT8* keyBuff=readFile(keyFileBuff,&keyFileBuffLen);
00438         m_pRSA->setPrivateKeyAsXML(keyBuff,keyFileBuffLen);
00439         delete[] keyFileBuff;
00440         delete[] keyBuff;
00441       }
00442     else
00443 #endif
00444       {
00445         m_pRSA->generateKeyPair(1024);
00446       }
00447 #ifdef EXPORT_ASYM_PRIVATE_KEY
00448     if(CALibProxytest::getOptions()->isExportKey())
00449       {
00450         UINT32 keyFileBuffLen=8096;
00451         UINT8* keyFileBuff=new UINT8[keyFileBuffLen];
00452         UINT8* keyBuff=new UINT8[keyFileBuffLen];
00453         CALibProxytest::getOptions()->getEncryptionKeyExportFile(keyFileBuff,keyFileBuffLen);
00454         m_pRSA->getPrivateKeyAsXML(keyBuff,&keyFileBuffLen);
00455         saveFile(keyFileBuff,keyBuff,keyFileBuffLen);
00456         delete[] keyFileBuff;
00457         delete[] keyBuff;
00458       }
00459 #endif
00460     DOMNode* child=elemMixes->getLastChild();
00461 
00462     //tmp XML-Structure for constructing the XML which is sent to each user
00463     XERCES_CPP_NAMESPACE::DOMDocument* docXmlKeyInfo=createDOMDocument();
00464     DOMElement* elemRootKey=createDOMElement(docXmlKeyInfo,"MixCascade");
00465     setDOMElementAttribute(elemRootKey,"version",(UINT8*)"0.2"); //set the Version of the XML to 0.2
00466 #ifdef LOG_DIALOG
00467     setDOMElementAttribute(elemRootKey,"study",(UINT8*)"true");
00468 #endif
00469     docXmlKeyInfo->appendChild(elemRootKey);
00470     DOMElement* elemMixProtocolVersion=createDOMElement(docXmlKeyInfo,"MixProtocolVersion");
00471     setDOMElementValue(elemMixProtocolVersion,(UINT8*)MIX_CASCADE_PROTOCOL_VERSION);
00472     elemRootKey->appendChild(elemMixProtocolVersion);
00473     DOMNode* elemMixesKey=docXmlKeyInfo->importNode(elemMixes,true);
00474     elemRootKey->appendChild(elemMixesKey);
00475 
00476     //UINT32 tlen;
00477     /* //remove because it seems to be useless...
00478     while(child!=NULL)
00479     {
00480         if(child.getNodeName().equals("Mix"))
00481         {
00482             DOM_Node rsaKey=child.getFirstChild();
00483             CAASymCipher oRSA;
00484             oRSA.setPublicKeyAsDOMNode(rsaKey);
00485             tlen=256;
00486         }
00487         child=child.getPreviousSibling();
00488     }*/
00489     //tlen=256;
00490 
00491     //Inserting own Key in XML-Key struct
00492     DOMElement* elemKey=NULL;
00493     m_pRSA->getPublicKeyAsDOMElement(elemKey,docXmlKeyInfo);
00494     addMixInfo(elemMixesKey, true);
00495     DOMElement* elemOwnMix=NULL;
00496     getDOMChildByName(elemMixesKey, "Mix", elemOwnMix, false);
00497     elemOwnMix->appendChild(elemKey);
00498     CAMsg::printMsg(LOG_INFO,"before T&Cs1...\n");
00499     if(CALibProxytest::getOptions()->getTermsAndConditions() != NULL)
00500     {
00501       elemOwnMix->appendChild(termsAndConditionsInfoNode(docXmlKeyInfo));
00502     }
00503     CAMsg::printMsg(LOG_INFO,"after T&Cs1...\n");
00504     elemOwnMix->appendChild(createDOMElement(docXmlKeyInfo,"SupportsEncrypedControlChannels"));
00505   CAMsg::printMsg(LOG_INFO,"after SupportEncChannels...\n");
00506   if (signXML(elemOwnMix) != E_SUCCESS)
00507   {
00508     CAMsg::printMsg(LOG_DEBUG,"Could not sign MixInfo sent to users...\n");
00509   }
00510 
00511   setDOMElementAttribute(elemMixesKey,"count",count+1);
00512 
00513 
00514   DOMNode* elemPayment=createDOMElement(docXmlKeyInfo,"Payment");
00515   elemRootKey->appendChild(elemPayment);
00516 #ifdef PAYMENT
00517   setDOMElementAttribute(elemPayment,"required",(UINT8*)"true");
00518   setDOMElementAttribute(elemPayment,"version",(UINT8*)PAYMENT_VERSION);
00519   setDOMElementAttribute(elemPayment,"prepaidInterval", CALibProxytest::getOptions()->getPrepaidInterval());
00520   setDOMElementAttribute(elemPayment,"piid", CALibProxytest::getOptions()->getBI()->getID());
00521 
00522 #else
00523   setDOMElementAttribute(elemPayment,"required",(UINT8*)"false");
00524 #endif
00525 
00526   // create signature
00527   if (signXML(elemRootKey) != E_SUCCESS)
00528     {
00529     CAMsg::printMsg(LOG_DEBUG,"Could not sign KeyInfo sent to users...\n");
00530   }
00531 
00532 
00533   UINT32 tmp32Len = 0;
00534     UINT8* tmpB=DOM_Output::dumpToMem(docXmlKeyInfo, &tmp32Len);
00535     if (docXmlKeyInfo != NULL)
00536     {
00537       docXmlKeyInfo->release();
00538       docXmlKeyInfo = NULL;
00539     }
00540 
00541     if(tmp32Len > 0xFFFD) //too bytes are reserved for the length
00542     {
00543     CAMsg::printMsg(LOG_CRIT, "The key info size of %u bytes is too large for the clients. (maximum is %u)\n", 0xFFFD);
00544     if (doc != NULL)
00545     {
00546       doc->release();
00547       doc = NULL;
00548     }
00549     return E_UNKNOWN;
00550     }
00551 
00552     UINT16 tlen = (UINT16) tmp32Len;
00553     m_xmlKeyInfoBuff = new UINT8[tlen+sizeof(tlen)];
00554     memcpy(m_xmlKeyInfoBuff+sizeof(tlen), tmpB, tlen);
00555     UINT16 s = htons(tlen);
00556     memcpy(m_xmlKeyInfoBuff, &s, sizeof(s));
00557     m_xmlKeyInfoSize=tlen + sizeof(tlen);
00558     delete []tmpB;
00559     tmpB = NULL;
00560     SINT32 result=E_UNKNOWN;
00561 
00562     //Sending symmetric key...
00563     child=elemMixes->getFirstChild();
00564     while(child!=NULL)
00565     {
00566       if(equals(child->getNodeName(),"Mix"))
00567         {
00568         //verify certificate from next mix if enabled
00569         if(CALibProxytest::getOptions()->verifyMixCertificates())
00570         {
00571           CACertificate* nextMixCert = CALibProxytest::getOptions()->getTrustedCertificateStore()->verifyMixCert(child);
00572           if(nextMixCert != NULL)
00573           {
00574             CAMsg::printMsg(LOG_DEBUG, "Next mix certificate was verified by a trusted root CA.\n");
00575             CALibProxytest::getOptions()->setNextMixTestCertificate(nextMixCert);
00576           }
00577           else
00578           {
00579             CAMsg::printMsg(LOG_ERR, "Could not verify certificate received from next mix!\n");
00580             return E_UNKNOWN;
00581           }
00582         }
00583             //check Signature....
00584             CAMsg::printMsg(LOG_DEBUG,"Try to verify next mix signature...\n");
00585             //CASignature oSig;
00586             CACertificate* nextCert=CALibProxytest::getOptions()->getNextMixTestCertificate();
00587             /*oSig.setVerifyKey(nextCert);
00588             SINT32 ret=oSig.verifyXML(child,NULL);*/
00589             result = CAMultiSignature::verifyXML(child, nextCert);
00590             delete nextCert;
00591             nextCert = NULL;
00592             if(result != E_SUCCESS)
00593             {     
00594                 //CAMsg::printMsg(LOG_CRIT,"Could not verify the symmetric key from next mix! The operator of the next mix has to send you his current mix certificate, and you will have to import it in your configuration. Alternatively, you might import the proper root certification authority for verifying the certificate.\n");
00595                 CAMsg::printMsg(LOG_CRIT,"Could not verify the symmetric key from next mix! The operator of the next mix has to send you his current mix certificate, and you will have to import it in your configuration.\n");
00596                 if (doc != NULL)
00597                 {
00598                   doc->release();
00599                   doc = NULL;
00600                 }
00601                 return E_UNKNOWN;
00602             }
00603             CAMsg::printMsg(LOG_DEBUG,"Successfully verified XML signature of next mix!\n");
00604 
00605             result = checkCompatibility(child, "next");
00606           
00607 
00608             DOMNode* rsaKey=child->getFirstChild();
00609             CAASymCipher oRSA;
00610             oRSA.setPublicKeyAsDOMNode(rsaKey);
00611             DOMElement* elemNonce=NULL;
00612             getDOMChildByName(child,"Nonce",elemNonce,false);
00613             UINT8 arNonce[1024];
00614             if(elemNonce!=NULL)
00615             {
00616                 UINT32 lenNonce=1024;
00617                 UINT32 tmpLen=1024;
00618                 getDOMElementValue(elemNonce,arNonce,&lenNonce);
00619                 CABase64::decode(arNonce,lenNonce,arNonce,&tmpLen);
00620                 lenNonce=tmpLen;
00621                 tmpLen=1024;
00622                 CABase64::encode(SHA1(arNonce,lenNonce,NULL),SHA_DIGEST_LENGTH,
00623                                  arNonce,&tmpLen);
00624                 arNonce[tmpLen]=0;
00625             }
00626             UINT8 key[64];
00627             getRandom(key,64);
00628             //UINT8 buff[400];
00629             //UINT32 bufflen=400;
00630             XERCES_CPP_NAMESPACE::DOMDocument* docSymKey=createDOMDocument();
00631             DOMElement* elemRoot=NULL;
00632             encodeXMLEncryptedKey(key,64,elemRoot,docSymKey,&oRSA);
00633             docSymKey->appendChild(elemRoot);
00634             if(elemNonce!=NULL)
00635             {
00636                 DOMElement* elemNonceHash=createDOMElement(docSymKey,"Nonce");
00637                 setDOMElementValue(elemNonceHash,arNonce);
00638                 elemRoot->appendChild(elemNonceHash);
00639             }
00640 
00641             appendCompatibilityInfo(elemRoot);
00642 
00644       DOMElement* elemKeepAlive=NULL;
00645       DOMElement* elemKeepAliveSendInterval=NULL;
00646       DOMElement* elemKeepAliveRecvInterval=NULL;
00647       getDOMChildByName(child,"KeepAlive",elemKeepAlive,false);
00648       getDOMChildByName(elemKeepAlive,"SendInterval",elemKeepAliveSendInterval,false);
00649       getDOMChildByName(elemKeepAlive,"ReceiveInterval",elemKeepAliveRecvInterval,false);
00650       UINT32 tmpSendInterval,tmpRecvInterval;
00651       getDOMElementValue(elemKeepAliveSendInterval,tmpSendInterval,0xFFFFFFFF); //if no send interval was given set it to "infinite"
00652       getDOMElementValue(elemKeepAliveRecvInterval,tmpRecvInterval,0xFFFFFFFF); //if no recv interval was given --> set it to "infinite"
00653       CAMsg::printMsg(LOG_DEBUG,"KeepAlive-Traffic: Getting offer -- SendInterval %u -- ReceiveInterval %u\n",tmpSendInterval,tmpRecvInterval);
00654       // Add Info about KeepAlive traffic
00655       UINT32 u32KeepAliveSendInterval=CALibProxytest::getOptions()->getKeepAliveSendInterval();
00656       UINT32 u32KeepAliveRecvInterval=CALibProxytest::getOptions()->getKeepAliveRecvInterval();
00657       elemKeepAlive=createDOMElement(docSymKey,"KeepAlive");
00658       elemKeepAliveSendInterval=createDOMElement(docSymKey,"SendInterval");
00659       elemKeepAliveRecvInterval=createDOMElement(docSymKey,"ReceiveInterval");
00660       elemKeepAlive->appendChild(elemKeepAliveSendInterval);
00661       elemKeepAlive->appendChild(elemKeepAliveRecvInterval);
00662       setDOMElementValue(elemKeepAliveSendInterval,u32KeepAliveSendInterval);
00663       setDOMElementValue(elemKeepAliveRecvInterval,u32KeepAliveRecvInterval);
00664       elemRoot->appendChild(elemKeepAlive);
00665       CAMsg::printMsg(LOG_DEBUG,"KeepAlive-Traffic: Offering -- SendInterval %u -- Receive Interval %u\n",u32KeepAliveSendInterval,u32KeepAliveRecvInterval);
00666       m_u32KeepAliveSendInterval = u32KeepAliveSendInterval;
00667       if (m_u32KeepAliveSendInterval > tmpRecvInterval - 10000)
00668         m_u32KeepAliveSendInterval-=10000; //make the send interval a little bit smaller than the related receive interval
00669       m_u32KeepAliveRecvInterval=max(u32KeepAliveRecvInterval,tmpSendInterval);
00670       if (m_u32KeepAliveRecvInterval - 10000 < tmpSendInterval)
00671         {
00672           m_u32KeepAliveRecvInterval += 10000;
00673         }
00674       CAMsg::printMsg(LOG_DEBUG,"KeepAlive-Traffic: Calculated -- SendInterval %u -- Receive Interval %u\n",m_u32KeepAliveSendInterval,m_u32KeepAliveRecvInterval);
00675 
00676       //m_pSignature->signXML(elemRoot);
00677       m_pMultiSignature->signXML(elemRoot, true);
00678       UINT32 outlen=0;
00679       UINT8* out=DOM_Output::dumpToMem(docSymKey,&outlen);
00680       if (docSymKey != NULL)
00681         {
00682           docSymKey->release();
00683           docSymKey = NULL;
00684         }
00685       m_pMuxOut->setSendKey(key,32);
00686       m_pMuxOut->setReceiveKey(key+32,32);
00687       UINT32 size = htonl(outlen);
00688       CAMsg::printMsg(LOG_DEBUG,"Sending symmetric key to next Mix! Size: %i\n", outlen);
00689       m_pMuxOut->getCASocket()->send((UINT8*) &size, sizeof(size));
00690       m_pMuxOut->getCASocket()->send(out, outlen);
00691       m_pMuxOut->setCrypt(true);
00692       delete[] out;
00693       out = NULL;
00694       break;
00695         }
00696         child=child->getNextSibling();
00697     }
00698   
00699    if (result != E_SUCCESS)
00700   {
00701     if (doc != NULL)
00702     {
00703       doc->release();
00704       doc = NULL;
00705     }
00706     return result;
00707   }
00708   
00709   
00711   if(initMixParameters(elemMixes)!=E_SUCCESS)
00712   {
00713     if (doc != NULL)
00714     {
00715       doc->release();
00716       doc = NULL;
00717     }
00718     return E_UNKNOWN;
00719   }
00720     if(initMixCascadeInfo(elemMixes)!=E_SUCCESS)
00721     {
00722       if (doc != NULL)
00723       {
00724         doc->release();
00725         doc = NULL;
00726       }
00727       CAMsg::printMsg(LOG_CRIT,"Error initializing cascade info.\n");
00728         return E_UNKNOWN;
00729     }
00730 /*    else
00731     {
00732         if(m_pInfoService != NULL)
00733             m_pInfoService->sendCascadeHelo();
00734     }*/
00735     CAMsg::printMsg(LOG_DEBUG,"Key exchange finished!\n");
00736     if (doc != NULL)
00737     {
00738       doc->release();
00739       doc = NULL;
00740     }
00741     return E_SUCCESS;
00742 }
00743 
00744 
00745 SINT32 CAFirstMix::setMixParameters(const tMixParameters& params)
00746   {
00747 #ifdef REPLAY_DETECTION
00748     UINT32 diff=time(NULL)-m_u64LastTimestampReceived;
00749     for(UINT32 i=0;i<m_u32MixCount-1;i++)
00750       {
00751 //@todo dangerous strcmp
00752         if(strcmp((char*)m_arMixParameters[i].m_strMixID,(char*)params.m_strMixID)==0)
00753           {
00754             m_arMixParameters[i].m_u32ReplayOffset=params.m_u32ReplayOffset;
00755             m_arMixParameters[i].m_u32ReplayBase=params.m_u32ReplayBase;
00756           }
00757         else{
00758             if (m_arMixParameters[i].m_u32ReplayOffset!=0) m_arMixParameters[i].m_u32ReplayOffset+=diff;
00759           }
00760       }
00761 #endif
00762     return E_SUCCESS;
00763   }
00764 
00765 
00766 SINT32 CAFirstMix::handleKeyInfoExtensions(DOMElement *root)
00767 {
00768   if(root == NULL)
00769   {
00770     return E_UNKNOWN;
00771   }
00772 
00773   SINT32 ret = E_SUCCESS;
00774   DOMElement *extensionRoot = NULL;
00775   getDOMChildByName(root, KEYINFO_NODE_EXTENSIONS, extensionRoot);
00776 
00777   if(extensionRoot != NULL)
00778   {
00779     extensionRoot = (DOMElement *) root->removeChild(extensionRoot);
00780     ret = handleTermsAndConditionsExtension(extensionRoot);
00781     extensionRoot->release();
00782   }
00783   return ret;
00784 }
00785 
00786 SINT32 CAFirstMix::handleTermsAndConditionsExtension(DOMElement *extensionsRoot)
00787 {
00788   if(extensionsRoot == NULL)
00789   {
00790     return E_UNKNOWN;
00791   }
00792 
00793   DOMElement *tncDefs = NULL;
00794   DOMElement *tncTemplates = NULL;
00795   getDOMChildByName(extensionsRoot, KEYINFO_NODE_TNC_EXTENSION, tncDefs);
00796   if(tncDefs == NULL)
00797   {
00798     CAMsg::printMsg(LOG_CRIT,"No TNCs in TNC extension found.\n");
00799     return E_UNKNOWN;
00800   }
00801   getDOMChildByName(tncDefs, OPTIONS_NODE_TNCS_TEMPLATES, tncTemplates);
00802 
00803   UINT8 currentTnC_id[TMP_BUFF_SIZE];
00804   UINT32 currentTnC_id_len = TMP_BUFF_SIZE;
00805 
00806   UINT8 currentTnCEntry_templateRefid[TMP_BUFF_SIZE];
00807   UINT32 currentTnCEntry_templateRefid_len = TMP_BUFF_SIZE;
00808 
00809   UINT8 currentTnCEntry_locale[TMP_LOCALE_SIZE];
00810   UINT32 currentTnCEntry_locale_len = TMP_LOCALE_SIZE;
00811 
00812   DOMElement *currentTnCList = NULL;
00813   DOMElement *currentTnCEntry = NULL;
00814   memset(currentTnC_id, 0, TMP_BUFF_SIZE);
00815   memset(currentTnCEntry_templateRefid, 0, TMP_BUFF_SIZE);
00816 
00817   if(tncTemplates != NULL)
00818   {
00819     DOMNodeList *tncTemplateList = getElementsByTagName(tncDefs, TNC_TEMPLATE_ROOT_ELEMENT);
00820     m_nrOfTermsAndConditionsTemplates = tncTemplateList->getLength();
00821     CAMsg::printMsg(LOG_INFO, "Storing %u TC Templates.\n", m_nrOfTermsAndConditionsTemplates);
00822     if(m_nrOfTermsAndConditionsTemplates > 0)
00823     {
00824       m_tcTemplates = new DOMNode *[m_nrOfTermsAndConditionsTemplates];
00825       for (UINT32 i = 0; i < m_nrOfTermsAndConditionsTemplates; i++)
00826       {
00827         m_tcTemplates[i] = m_templatesOwner->importNode(tncTemplateList->item(i), true);
00828       }
00829     }
00830     else
00831     {
00832       CAMsg::printMsg(LOG_ERR, "Not a single TC Template specified! the Cascade is not properly configured.\n");
00833       return E_UNKNOWN;
00834     }
00835   }
00836   else
00837   {
00838     CAMsg::printMsg(LOG_ERR, "No TC Template node found! Cascade is not properly configured.\n");
00839     return E_UNKNOWN;
00840   }
00841 
00842   DOMNodeList *tncDefList = getElementsByTagName(tncDefs, OPTIONS_NODE_TNCS);
00843   if(tncDefList->getLength() == 0)
00844   {
00845     CAMsg::printMsg(LOG_CRIT, "No TNCs definitions found.\n");
00846     return E_UNKNOWN;
00847   }
00848 
00849   m_nrOfTermsAndConditionsDefs = tncDefList->getLength();
00850   m_tnCDefs = new TermsAndConditions *[m_nrOfTermsAndConditionsDefs];
00851   memset(m_tnCDefs, 0, (sizeof(TermsAndConditions*)*m_nrOfTermsAndConditionsDefs) );
00852 
00853   for (XMLSize_t i = 0; i < m_nrOfTermsAndConditionsDefs; i++)
00854   {
00855     currentTnCList = (DOMElement *) tncDefList->item(i);
00856     DOMNodeList *tncDefEntryList = getElementsByTagName(currentTnCList, OPTIONS_NODE_TNCS_TRANSLATION);
00857     getDOMElementAttribute(currentTnCList, OPTIONS_ATTRIBUTE_TNC_ID, currentTnC_id, &currentTnC_id_len);
00858 
00859     m_tnCDefs[i] = new TermsAndConditions(currentTnC_id, tncDefEntryList->getLength());
00860 
00861     for (XMLSize_t j = 0; j < tncDefEntryList->getLength(); j++)
00862     {
00863       currentTnCEntry = (DOMElement *) tncDefEntryList->item(j);
00864 
00865       getDOMElementAttribute(currentTnCEntry, OPTIONS_ATTRIBUTE_TNC_TEMPLATE_REFID,
00866           currentTnCEntry_templateRefid, &currentTnCEntry_templateRefid_len);
00867       getDOMElementAttribute(currentTnCEntry, OPTIONS_ATTRIBUTE_TNC_LOCALE,
00868           currentTnCEntry_locale, &currentTnCEntry_locale_len);
00869 
00870       DOMNode *templateNode = getTermsAndConditionsTemplate(currentTnCEntry_templateRefid);
00871       if(templateNode != NULL)
00872       {
00873         //m_tnCDefs[i]->synchLock->lock();
00874         m_tnCDefs[i]->addTranslation(currentTnCEntry_locale, currentTnCEntry, templateNode);
00875         //m_tnCDefs[i]->synchLock->unlock();
00876       }
00877       else
00878       {
00879         CAMsg::printMsg(LOG_CRIT,"Could not find template %s for T&C %s.\n", currentTnCEntry_templateRefid, currentTnC_id);
00880         return E_UNKNOWN;
00881       }
00882       memset(currentTnCEntry_templateRefid, 0, TMP_BUFF_SIZE);
00883       currentTnCEntry_templateRefid_len = TMP_BUFF_SIZE;
00884       memset(currentTnCEntry_locale, 0, TMP_LOCALE_SIZE);
00885       currentTnCEntry_locale_len = TMP_LOCALE_SIZE;
00886     }
00887     memset(currentTnC_id, 0, TMP_BUFF_SIZE);
00888     currentTnC_id_len = TMP_BUFF_SIZE;
00889   }
00890   return E_SUCCESS;
00891 }
00892 
00893 TermsAndConditions *CAFirstMix::getTermsAndConditions(const UINT8 *opSki)
00894 {
00895   if( (m_tnCDefs == NULL) || (opSki == NULL) )
00896   {
00897     return NULL;
00898   }
00899   for(UINT32 i = 0; i < m_nrOfTermsAndConditionsDefs; i++)
00900   {
00901     if(m_tnCDefs[i] != NULL)
00902     {
00903       if(strncasecmp((char *) m_tnCDefs[i]->getID(),
00904               (const char *) opSki,
00905               strlen((char *) m_tnCDefs[i]->getID())) == 0)
00906       {
00907         return m_tnCDefs[i];
00908       }
00909     }
00910   }
00911   return NULL;
00912 }
00913 
00914 DOMNode *CAFirstMix::getTermsAndConditionsTemplate(UINT8 *templateRefID)
00915 {
00916   UINT8 *currentRefId = NULL;
00917   bool match = false;
00918 
00919   for (UINT32 i = 0; i < m_nrOfTermsAndConditionsTemplates; i++)
00920   {
00921     currentRefId = getTermsAndConditionsTemplateRefId(m_tcTemplates[i]);
00922     match = (currentRefId != NULL) &&
00923          (strncmp((char *)templateRefID, (char *)currentRefId, TEMPLATE_REFID_MAXLEN ) == 0);
00924     delete [] currentRefId;
00925     currentRefId = NULL;
00926     if(match)
00927     {
00928       return m_tcTemplates[i];
00929     }
00930   }
00931   return NULL;
00932 }
00933 
00939 THREAD_RETURN fm_loopSendToMix(void* param)
00940   {
00941     INIT_STACK;
00942     BEGIN_STACK("CAFirstMix::fm_loopSendToMix");
00943 
00944     CAFirstMix* pFirstMix=(CAFirstMix*)param;
00945     CAQueue* pQueue=((CAFirstMix*)param)->m_pQueueSendToMix;
00946     CAMuxSocket* pMuxSocket=pFirstMix->m_pMuxOut;
00947 
00948     UINT32 len;
00949     SINT32 ret;
00950 
00951 /*#ifdef DATA_RETENTION_LOG
00952     t_dataretentionLogEntry* pDataRetentionLogEntry=new t_dataretentionLogEntry;
00953 #endif
00954 */
00955 #ifndef USE_POOL
00956     tQueueEntry* pQueueEntry=new tQueueEntry;
00957     MIXPACKET* pMixPacket=&pQueueEntry->packet;
00958     UINT32 u32KeepAliveSendInterval=pFirstMix->m_u32KeepAliveSendInterval;
00959     while(!pFirstMix->m_bRestart)
00960       {
00961         len=sizeof(tQueueEntry);
00962         ret=pQueue->getOrWait((UINT8*)pQueueEntry,&len,u32KeepAliveSendInterval);
00963         if(ret==E_TIMEDOUT)
00964           {//send a dummy as keep-alvie-traffic
00965             pMixPacket->flags=CHANNEL_DUMMY;
00966             pMixPacket->channel=DUMMY_CHANNEL;
00967             getRandom(pMixPacket->data,DATA_SIZE);
00968           }
00969         else if(ret!=E_SUCCESS||len!=sizeof(tQueueEntry))
00970           {
00971             CAMsg::printMsg(LOG_ERR,"CAFirstMix::lm_loopSendToMix - Error in dequeueing MixPaket\n");
00972             CAMsg::printMsg(LOG_ERR,"ret=%i len=%i\n",ret,len);
00973             break;
00974           }
00975 
00976         if(pMuxSocket->send(pMixPacket)!=MIXPACKET_SIZE)
00977           {
00978             CAMsg::printMsg(LOG_ERR,"CAFirstMix::lm_loopSendToMix - Error in sending MixPaket\n");
00979             break;
00980           }
00981 #if defined (LOG_PACKET_TIMES)
00982         if(!isZero64(pQueueEntry->timestamp_proccessing_start))
00983           {
00984             getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end);
00985             pFirstMix->m_pLogPacketStats->addToTimeingStats(*pQueueEntry,pMixPacket->flags,true);
00986           }
00987 #endif
00988 #ifdef DATA_RETENTION_LOG
00989         if((pQueueEntry->packet.flags&CHANNEL_OPEN)!=0)
00990           {
00991             pQueueEntry->dataRetentionLogEntry.t_out=htonl(time(NULL));
00992             pFirstMix->m_pDataRetentionLog->log(&(pQueueEntry->dataRetentionLogEntry));
00993           }
00994 #endif
00995       }
00996     delete pQueueEntry;
00997     pQueueEntry = NULL;
00998 #else
00999     CAPool* pPool=new CAPool(MIX_POOL_SIZE);
01000     tPoolEntry* pPoolEntry=new tPoolEntry;
01001     MIXPACKET* pMixPacket=&pPoolEntry->packet;
01002     while(!pFirstMix->m_bRestart)
01003       {
01004         len=sizeof(tQueueEntry);
01005         ret=pQueue->getOrWait((UINT8*)pPoolEntry,&len,MIX_POOL_TIMEOUT);
01006         if(ret==E_TIMEDOUT)
01007           {
01008             pMixPacket->flags=CHANNEL_DUMMY;
01009             pMixPacket->channel=DUMMY_CHANNEL;
01010             getRandom(pMixPacket->data,DATA_SIZE);
01011             #ifdef LOG_PACKET_TIMES
01012               setZero64(pPoolEntry->timestamp_proccessing_start);
01013             #endif
01014           }
01015         else if(ret!=E_SUCCESS||len!=sizeof(tQueueEntry))
01016           break;
01017         #ifdef LOG_PACKET_TIMES
01018           getcurrentTimeMicros(pPoolEntry->pool_timestamp_in);
01019         #endif
01020         pPool->pool(pPoolEntry);
01021         #ifdef LOG_PACKET_TIMES
01022           getcurrentTimeMicros(pPoolEntry->pool_timestamp_out);
01023         #endif
01024         if(pMuxSocket->send(pMixPacket)!=MIXPACKET_SIZE)
01025           break;
01026         #ifdef LOG_PACKET_TIMES
01027           if(!isZero64(pPoolEntry->timestamp_proccessing_start))
01028             {
01029               getcurrentTimeMicros(pPoolEntry->timestamp_proccessing_end);
01030               pFirstMix->m_pLogPacketStats->addToTimeingStats(*pPoolEntry,pMixPacket->flags,true);
01031             }
01032         #endif
01033       }
01034     delete pPoolEntry;
01035     pPoolEntry = NULL;
01036     delete pPool;
01037     pPool = NULL;
01038 #endif
01039 
01040 /*#ifdef DATA_RETENTION_LOG
01041     delete pDataRetentionLogEntry;
01042 #endif
01043 */
01044     FINISH_STACK("CAFirstMix::fm_loopSendToMix");
01045 
01046     CAMsg::printMsg(LOG_DEBUG,"Exiting Thread SendToMix\n");
01047     THREAD_RETURN_SUCCESS;
01048   }
01049 
01050 /* How to end this thread:
01051   0. set bRestart=true
01052 */
01053 THREAD_RETURN fm_loopReadFromMix(void* pParam)
01054   {
01055     INIT_STACK;
01056     BEGIN_STACK("CAFirstMix::fm_loopReadFromMix");
01057 
01058     CAFirstMix* pFirstMix=(CAFirstMix*)pParam;
01059     CAMuxSocket* pMuxSocket=pFirstMix->m_pMuxOut;
01060     CAQueue* pQueue=pFirstMix->m_pQueueReadFromMix;
01061     tQueueEntry* pQueueEntry=new tQueueEntry;
01062     MIXPACKET* pMixPacket=&pQueueEntry->packet;
01063     CASingleSocketGroup* pSocketGroup=new CASingleSocketGroup(false);
01064     pSocketGroup->add(*pMuxSocket);
01065     #ifdef USE_POOL
01066       CAPool* pPool=new CAPool(MIX_POOL_SIZE);
01067     #endif
01068     UINT64 keepaliveNow,keepaliveLast;
01069     UINT32 u32KeepAliveRecvInterval=pFirstMix->m_u32KeepAliveRecvInterval;
01070     getcurrentTimeMillis(keepaliveLast);
01071     CAControlChannelDispatcher* pControlChannelDispatcher=pFirstMix->m_pMuxOutControlChannelDispatcher;
01072     while(!pFirstMix->m_bRestart)
01073       {
01074         if(pQueue->getSize()>MAX_READ_FROM_NEXT_MIX_QUEUE_SIZE)
01075           {
01076 #ifdef DEBUG
01077             CAMsg::printMsg(LOG_DEBUG,"CAFirstMix::Queue is full!\n");
01078 #endif
01079             msSleep(200);
01080             getcurrentTimeMillis(keepaliveLast);
01081             continue;
01082           }
01083         //check if the connection is broken because we did not received a Keep_alive-Message
01084         getcurrentTimeMillis(keepaliveNow);
01085         UINT32 keepaliveDiff=diff64(keepaliveNow,keepaliveLast);
01086         if(keepaliveDiff>u32KeepAliveRecvInterval)
01087           {
01088             CAMsg::printMsg(LOG_DEBUG,"CAFirstMix::loopReadFromMix() -- restart because of KeepAlive-Traffic Timeout!\n");
01089             pFirstMix->m_bRestart=true;
01090             MONITORING_FIRE_NET_EVENT(ev_net_nextConnectionClosed);
01091             break;
01092           }
01093         SINT32 ret=pSocketGroup->select(MIX_POOL_TIMEOUT);
01094         if(ret==E_TIMEDOUT)
01095           {
01096             #ifdef USE_POOL
01097               pMixPacket->flags=CHANNEL_DUMMY;
01098               pMixPacket->channel=DUMMY_CHANNEL;
01099               getRandom(pMixPacket->data,DATA_SIZE);
01100               #ifdef LOG_PACKET_TIMES
01101                 setZero64(pQueueEntry->timestamp_proccessing_start);
01102               #endif
01103             #else
01104               continue;
01105             #endif
01106           }
01107         else if(ret>0)
01108           {
01109             ret=pMuxSocket->receive(pMixPacket);
01110             #ifdef LOG_PACKET_TIMES
01111               getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_start);
01112             #endif
01113             if(ret!=MIXPACKET_SIZE)
01114               {
01115                 pFirstMix->m_bRestart=true;
01116                 CAMsg::printMsg(LOG_ERR,"CAFirstMix::lm_loopReadFromMix - received returned: %i -- restarting!\n",ret);
01117                 MONITORING_FIRE_NET_EVENT(ev_net_nextConnectionClosed);
01118                 break;
01119               }
01120           }
01121           if(pMixPacket->channel>0&&pMixPacket->channel<256)
01122             {
01123               #ifdef DEBUG
01124                 CAMsg::printMsg(LOG_DEBUG,"CAFirstMix - sent a packet from the next mix to the ControlChanelDispatcher... \n");
01125               #endif
01126               pControlChannelDispatcher->proccessMixPacket(pMixPacket);
01127               getcurrentTimeMillis(keepaliveLast);
01128               continue;
01129             }
01130         #ifdef USE_POOL
01131           #ifdef LOG_PACKET_TIMES
01132             getcurrentTimeMicros(pQueueEntry->pool_timestamp_in);
01133           #endif
01134           pPool->pool((tPoolEntry*)pQueueEntry);
01135           #ifdef LOG_PACKET_TIMES
01136             getcurrentTimeMicros(pQueueEntry->pool_timestamp_out);
01137           #endif
01138         #endif
01139         pQueue->add(pQueueEntry, sizeof(tQueueEntry));
01140         getcurrentTimeMillis(keepaliveLast);
01141       }
01142     delete pQueueEntry;
01143     pQueueEntry = NULL;
01144     delete pSocketGroup;
01145     pSocketGroup = NULL;
01146     #ifdef USE_POOL
01147       delete pPool;
01148       pPool = NULL;
01149     #endif
01150 
01151     FINISH_STACK("CAFirstMix::fm_loopReadFromMix");
01152     THREAD_RETURN_SUCCESS;
01153   }
01154 
01155 struct T_UserLoginData
01156   {
01157     CAMuxSocket* pNewUser;
01158     CAFirstMix* pMix;
01159     UINT8 peerIP[4];
01160   };
01161 
01162 typedef struct T_UserLoginData t_UserLoginData;
01163 
01164 SINT32 isAllowedToPassRestrictions(CASocket* pNewMuxSocket)
01165 {
01166   UINT8* peerIP=new UINT8[4];
01167   SINT32 master = pNewMuxSocket->getPeerIP(peerIP);
01168 
01169   if(master == E_SUCCESS)
01170   {
01171     UINT32 size=0;
01172     UINT8 remoteIP[4];
01173 
01174     CAListenerInterface** intf = CALibProxytest::getOptions()->getInfoServices(size);
01175 
01176     master = E_UNKNOWN;
01177 
01178     for(UINT32 i = 0; i < size; i++)
01179     {
01180       if(intf[i]->getType() == HTTP_TCP || intf[i]->getType() == RAW_TCP)
01181       {
01182         CASocketAddrINet* addr = (CASocketAddrINet*) intf[i]->getAddr();
01183         if(addr == NULL)
01184         {
01185           continue;
01186         }
01187 
01188         addr->getIP(remoteIP);
01189         delete addr;
01190         addr = NULL;
01191 
01192         if(memcmp(peerIP, remoteIP, 4) == 0)
01193         {
01194           CAMsg::printMsg(LOG_DEBUG,"Got InfoService connection: You are allowed for login...\n");
01195           master = E_SUCCESS;
01196           break;
01197         }
01198       }
01199     }
01200   }
01201   delete[] peerIP;
01202   peerIP = NULL;
01203 
01204   return master;
01205 }
01206 
01207 
01208 /*How to end this thread
01209 1. Set m_bRestart in firstMix to true
01210 2. close all accept sockets
01211 */
01212 THREAD_RETURN fm_loopAcceptUsers(void* param)
01213   {
01214     INIT_STACK;
01215     BEGIN_STACK("CAFirstMix::fm_loopAcceptUsers");
01216 
01217     CAFirstMix* pFirstMix=(CAFirstMix*)param;
01218     CASocket** socketsIn=pFirstMix->m_arrSocketsIn;
01219     CAIPList* pIPList=pFirstMix->m_pIPList;
01220     CATempIPBlockList* pIPBlockList = pFirstMix->m_pIPBlockList;
01221     CAThreadPool* pthreadsLogin=pFirstMix->m_pthreadsLogin;
01222     UINT32 nSocketsIn=pFirstMix->m_nSocketsIn;
01223     CASocketGroup* psocketgroupAccept=new CASocketGroup(false);
01224     CAMuxSocket* pNewMuxSocket;
01225     UINT8* peerIP=new UINT8[4];
01226     UINT32 i=0;
01227     SINT32 countRead;
01228     SINT32 ret;
01229     SINT32 retPeerIP = E_SUCCESS;
01230 
01231     pFirstMix->m_newConnections = 0;
01232 
01233     // kick out users that already have connected
01234     for(i=0;i<nSocketsIn;i++)
01235     {
01236         while (socketsIn[i]->close() != E_SUCCESS)
01237         {
01238           sSleep(1);
01239         }
01240     }
01241     if (CALibProxytest::getOptions()->createSockets(false,pFirstMix-> m_arrSocketsIn, pFirstMix->m_nSocketsIn) != E_SUCCESS)
01242     {
01243       goto END_THREAD;
01244     }
01245     for(i=0;i<nSocketsIn;i++)
01246     {
01247       psocketgroupAccept->add(*socketsIn[i]);
01248     }
01249 #ifdef REPLAY_DETECTION //before we can start to accept users we have to ensure that we received the replay timestamps form the over mixes
01250     CAMsg::printMsg(LOG_DEBUG,"Waiting for Replay Timestamp from next mixes\n");
01251     i=0;
01252     while(!pFirstMix->m_bRestart && i < pFirstMix->m_u32MixCount-1)
01253     {
01254       if(pFirstMix->m_arMixParameters[i].m_u32ReplayOffset==0)//not set yet
01255         {
01256           msSleep(100);//wait a little bit and try again
01257           continue;
01258         }
01259       i++;
01260     }
01261     CAMsg::printMsg(LOG_DEBUG,"All Replay Timestamp received\n");
01262 #endif
01263     while(!pFirstMix->m_bRestart)
01264       {
01265         if (pIPBlockList->count()>40)
01266         {
01267           CAMsg::printMsg(LOG_DEBUG,"UserAcceptLoop: login timeout list counts %d. We have %d users, %d open sockets and %d new connections. Restarting server sockets...\n",pIPBlockList->count(), pFirstMix->getNrOfUsers() ,CASocket::countOpenSockets(), pFirstMix->m_newConnections);
01268           for(i=0;i<nSocketsIn;i++)
01269           {
01270             psocketgroupAccept->remove(*socketsIn[i]);
01271             while (socketsIn[i]->close() != E_SUCCESS)
01272             {
01273               sSleep(1);
01274             }
01275           }
01276   
01277           if (CALibProxytest::getOptions()->createSockets(false,pFirstMix-> m_arrSocketsIn, pFirstMix->m_nSocketsIn) != E_SUCCESS)
01278           {
01279             // could not listen
01280             goto END_THREAD;
01281           }
01282           for(i=0;i<nSocketsIn;i++)
01283           {
01284             psocketgroupAccept->add(*socketsIn[i]);
01285           }
01286           sSleep(1);
01287         }
01288         countRead=psocketgroupAccept->select(10000);
01289         if(countRead<0)
01290           { //check for Error - are we restarting ?
01291             if(pFirstMix->m_bRestart ||countRead!=E_TIMEDOUT)
01292               goto END_THREAD;
01293           }
01294         i=0;
01295 #ifdef _DEBUG
01296         CAMsg::printMsg(LOG_DEBUG,"UserAcceptLoop: countRead=%i\n",countRead);
01297 #endif
01298         while(countRead>0&&i<nSocketsIn)
01299         {
01300           if(psocketgroupAccept->isSignaled(*socketsIn[i]))
01301           {
01302             countRead--;
01303             #ifdef _DEBUG
01304               CAMsg::printMsg(LOG_DEBUG,"New direct Connection from Client!\n");
01305             #endif
01306             pNewMuxSocket=new CAMuxSocket;
01307             ret=socketsIn[i]->accept(*(pNewMuxSocket->getCASocket()));
01308             pFirstMix->incNewConnections();
01309 
01310             if(ret!=E_SUCCESS)
01311             {
01312               // may return E_SOCKETCLOSED or E_SOCKET_LIMIT
01313               CAMsg::printMsg(LOG_ERR,"Accept Error %u - direct Connection from Client!\n",GET_NET_ERROR);
01314             }
01315             else if( (CALibProxytest::getOptions()->getMaxNrOfUsers() > 0 &&
01316                 pFirstMix->getNrOfUsers() >= CALibProxytest::getOptions()->getMaxNrOfUsers())
01317                 && (isAllowedToPassRestrictions(pNewMuxSocket->getCASocket()) != E_SUCCESS)
01318 
01319                 )
01320             {
01321               CAMsg::printMsg(LOG_DEBUG,"CAFirstMix User control: Too many users (Maximum:%d)! Rejecting user...\n", pFirstMix->getNrOfUsers(),CALibProxytest::getOptions()->getMaxNrOfUsers());
01322               ret = E_UNKNOWN;
01323             }
01324             else if ((pFirstMix->m_newConnections > CAFirstMix::MAX_CONCURRENT_NEW_CONNECTIONS)
01325                 && (isAllowedToPassRestrictions(pNewMuxSocket->getCASocket()) != E_SUCCESS)
01326                 )
01327 
01328             {
01329               /* This should protect the mix from flooding attacks
01330                * No more than MAX_CONCURRENT_NEW_CONNECTIONS are allowed.
01331                */
01332 #ifdef _DEBUG
01333               CAMsg::printMsg(LOG_DEBUG,"CAFirstMix Flooding protection: Too many concurrent new connections (Maximum:%d)! Rejecting user...\n", CAFirstMix::MAX_CONCURRENT_NEW_CONNECTIONS);
01334 #endif
01335               ret = E_UNKNOWN;
01336             }
01337 //#ifndef PAYMENT
01338             else if ((ret = pNewMuxSocket->getCASocket()->getPeerIP(peerIP)) != E_SUCCESS ||
01339                 (retPeerIP = pIPList->insertIP(peerIP)) < 0) 
01340                 // || (pIPBlockList->checkIP(peerIP) == E_UNKNOWN && isAllowedToPassRestrictions(pNewMuxSocket->getCASocket()) != E_SUCCESS))
01341             {
01342               if (ret != E_SUCCESS)
01343               {
01344                 CAMsg::printMsg(LOG_DEBUG,"Could not insert IP address as IP could not be retrieved! We have %d login threads currently running.\n", pthreadsLogin->countRequests()); 
01345   
01346               }
01347               else if (retPeerIP < 0)
01348               {
01349                 CAMsg::printMsg(LOG_DEBUG,"CAFirstMix Flooding protection: Could not insert IP address! We have %d login threads currently running.\n", pthreadsLogin->countRequests()); 
01350                 pIPBlockList->insertIP(peerIP);
01351               }
01352               else if (pIPBlockList->checkIP(peerIP) == E_UNKNOWN)
01353               {
01354                 CAMsg::printMsg(LOG_DEBUG, "Client IP address %u.%u.x.x is temporarily blocked! User login denied. We have %d open sockets and %d new connections.\n", peerIP[0],peerIP[1], CASocket::countOpenSockets(), pFirstMix->m_newConnections);
01355                 pIPList->removeIP(peerIP);
01356               } 
01357               ret = E_UNKNOWN;
01358             }
01359 //#endif
01360             else
01361             {
01362               t_UserLoginData* d=new t_UserLoginData;
01363               d->pNewUser=pNewMuxSocket;
01364               d->pMix=pFirstMix;
01365               memcpy(d->peerIP,peerIP,4);
01366 #ifdef DEBUG
01367               CAMsg::printMsg(LOG_DEBUG,"%d concurrent client connections.\n", pFirstMix->m_newConnections);
01368 #endif
01369               if(pthreadsLogin->addRequest(fm_loopDoUserLogin,d)!=E_SUCCESS)
01370               {
01371                 CAMsg::printMsg(LOG_ERR,"Could not add an login request to the login thread pool!\n");
01372                 ret=E_UNKNOWN;
01373               }
01374             }
01375 
01376             if (ret != E_SUCCESS)
01377             {
01378               delete pNewMuxSocket;
01379               pNewMuxSocket = NULL;
01380               pFirstMix->decNewConnections();
01381               if(ret==E_SOCKETCLOSED&&pFirstMix->m_bRestart) //Hm, should we restart ??
01382               {
01383                 goto END_THREAD;
01384               }
01385               else //if(ret==E_SOCKET_LIMIT) // Hm no free sockets - wait some time to hope to get a free one...
01386               {
01387                 msSleep(400);
01388               }
01389             }
01390           }
01391           i++;
01392         }
01393       }
01394 END_THREAD:
01395     FINISH_STACK("CAFirstMix::fm_loopAcceptUsers");
01396 
01397     delete[] peerIP;
01398     peerIP = NULL;
01399     delete psocketgroupAccept;
01400     psocketgroupAccept = NULL;
01401 
01402     CAMsg::printMsg(LOG_DEBUG,"Exiting Thread AcceptUser\n");
01403     THREAD_RETURN_SUCCESS;
01404   }
01405 
01406 
01407 THREAD_RETURN fm_loopLog(void* param)
01408   {
01409     CAFirstMix* pFirstMix=(CAFirstMix*)param;
01410     pFirstMix->m_bRunLog=true;
01411     UINT32 countLog=0;
01412     while(pFirstMix->m_bRunLog)
01413       {
01414         if(countLog==0)
01415           {
01416             logMemoryUsage();
01417             countLog=10;
01418           }
01419         sSleep(30);
01420         countLog--;
01421       }
01422     THREAD_RETURN_SUCCESS;
01423   }
01424 
01425 #ifdef CH_LOG_STUDY
01426 THREAD_RETURN fm_loopLogChannelsOpened(void* param)
01427   {
01428     CAFirstMix* pFirstMix=(CAFirstMix*)param;
01429     pFirstMix->m_bRunLog=true;
01430     UINT32 countLog= 10;
01431     UINT32 value = 0;
01432     UINT32 total = 0;
01433     time_t newIvalTS = 0, ival = 0;
01434 
01435     pFirstMix->nrOfChOpMutex->lock();
01436     pFirstMix->lastLogTime = time(NULL);
01437     pFirstMix->nrOfChOpMutex->unlock();
01438 
01439     while(pFirstMix->m_bRunLog)
01440     {
01441       if(countLog == 0)
01442       {
01443         pFirstMix->nrOfChOpMutex->lock();
01444         value = pFirstMix->nrOfOpenedChannels;
01445         total = pFirstMix->currentOpenedChannels;
01446         pFirstMix->nrOfOpenedChannels = 0;
01447         newIvalTS = time(NULL);
01448         ival = newIvalTS - pFirstMix->lastLogTime;
01449         pFirstMix->lastLogTime = newIvalTS;
01450         pFirstMix->nrOfChOpMutex->unlock();
01451         CAMsg::printMsg(LOG_INFO,"Analyzing channels: Opened channels for %u JonDo connections in the last %u seconds, overall open channels: %u, users online: %u\n",
01452             value, ival, total, pFirstMix->getNrOfUsers() );
01453         countLog = 10;
01454       }
01455       sSleep(1);
01456       countLog--;
01457     }
01458     THREAD_RETURN_SUCCESS;
01459   }
01460 #endif //CH_LOG_STUDY
01461 
01462 THREAD_RETURN fm_loopDoUserLogin(void* param)
01463   {
01464     INIT_STACK;
01465     BEGIN_STACK("CAFirstMix::fm_loopDoUserLogin");
01466 #ifdef COUNTRY_STATS
01467     my_thread_init();
01468 #endif
01469 
01470     t_UserLoginData* d=(t_UserLoginData*)param;
01471     d->pMix->doUserLogin(d->pNewUser,d->peerIP);
01472 
01473     SAVE_STACK("CAFirstMix::fm_loopDoUserLogin", "after user login");
01474     d->pMix->decNewConnections();
01475     delete d;
01476     d = NULL;
01477 
01478 #ifdef COUNTRY_STATS
01479     my_thread_end();
01480 #endif
01481     FINISH_STACK("CAFirstMix::fm_loopDoUserLogin");
01482 
01483     THREAD_RETURN_SUCCESS;
01484   }
01485 
01486 termsAndConditionMixAnswer_t *CAFirstMix::handleTermsAndConditionsLogin(XERCES_CPP_NAMESPACE::DOMDocument* request)
01487 {
01488   termsAndConditionMixAnswer_t *answer =
01489     new termsAndConditionMixAnswer_t;
01490 
01491   const XMLCh* reqName = request->getDocumentElement()->getTagName();
01492 
01493   //Client requests lacking T&C resources.
01494   if(XMLString::equals(reqName, TNC_REQUEST))
01495   {
01496     answer->result = TC_UNFINISHED;
01497     CAMsg::printMsg(LOG_DEBUG,"Handling TC request.\n");
01498     XERCES_CPP_NAMESPACE::DOMDocument *response = createDOMDocument();
01499     DOMElement *responseRoot = createDOMElement(response, TNC_RESPONSE);
01500     response->appendChild(responseRoot);
01501     //All elements with tag name 'Resources' (direct children of 'TermsAndConditionsRequest')
01502     DOMNodeList *requestedResources = getElementsByTagName(request->getDocumentElement(), TNC_RESOURCES);
01503     //All elements with tag name 'Translation' (direct children of 'Resources')
01504     DOMNodeList *requestedResourceItems = NULL;
01505 
01506     DOMNode *currentNode = NULL;
01507     DOMNode *currentAnswerNode = NULL;
01508     DOMNode *currentAnswerResourceNode = NULL;
01509 
01510     UINT32 idLen = TMP_BUFF_SIZE;
01511     UINT8 id[TMP_BUFF_SIZE];
01512     memset(id, 0, idLen);
01513 
01514     UINT32 localeLen = TMP_LOCALE_SIZE;
01515     UINT8 locale[TMP_LOCALE_SIZE];
01516     memset(locale, 0, localeLen);
01517 
01518     bool resourceError = false;
01519 
01520     if(requestedResources->getLength() == 0)
01521     {
01522       response->release();
01523       response = createDOMDocument();
01524       response->appendChild(createDOMElement(response, TNC_RESPONSE_INVALID_REQUEST));
01525       answer->result = TC_FAILED;
01526     }
01527 
01528     for (XMLSize_t i = 0; i < requestedResources->getLength(); i++)
01529     {
01530       idLen = TMP_BUFF_SIZE;
01531       localeLen = TMP_LOCALE_SIZE;
01532       bool validResource = false;
01533 
01534       currentNode = requestedResources->item(i);
01535       //check validity of the T&C resource request. attributes "id" and locale must be proper set.
01536       if( (getDOMElementAttribute(currentNode, OPTIONS_ATTRIBUTE_TNC_ID, id, &idLen) != E_SUCCESS) ||
01537         (strlen((char *)id) < 1)  )
01538       {
01539         CAMsg::printMsg(LOG_DEBUG,"Error: invalid id.\n");
01540         resourceError = true;
01541       }
01542 
01543       if(!currentNode->hasChildNodes())
01544       {
01545         //Empty Resource node is invalid!
01546         CAMsg::printMsg(LOG_DEBUG,"Error: No children.\n");
01547         resourceError = true;
01548       }
01549 
01550       if(!resourceError)
01551       {
01552 
01553         TermsAndConditions *requestedTnC = getTermsAndConditions(id);
01554         if(requestedTnC != NULL)
01555         {
01556           requestedResourceItems = getElementsByTagName((DOMElement *)currentNode, TNC_REQ_TRANSLATION);
01557           for(XMLSize_t j = 0; j < requestedResourceItems->getLength(); j++)
01558           {
01559             validResource = false;
01560             localeLen = TMP_LOCALE_SIZE;
01561             if( (getDOMElementAttribute(requestedResourceItems->item(j),
01562                 OPTIONS_ATTRIBUTE_TNC_LOCALE,
01563                 locale, &localeLen) != E_SUCCESS) ||
01564               (strlen((char *)locale) != ((TMP_LOCALE_SIZE) - 1) ) )
01565             {
01566               CAMsg::printMsg(LOG_DEBUG,"Error: Invalid locale for tnc %s\n", id);
01567               break;
01568             }
01569 
01570             const termsAndConditionsTranslation_t *requestedTranslation =
01571                 requestedTnC->getTranslation(locale);
01572             //NOTE: No need to lock while working with the TC translation
01573             //because the translation containers are only modified during
01574             //inter-mix-keyexchange and cleanup.
01575             //Both must never run concurrently to this method
01576             if(requestedTranslation != NULL)
01577             {
01578 
01579               currentAnswerNode = response->importNode(currentNode, false);
01580               responseRoot->appendChild(currentAnswerNode);
01581               if( getDOMChildByName(requestedResourceItems->item(j), TNC_RESOURCE_TEMPLATE,
01582                   currentAnswerResourceNode, false) == E_SUCCESS)
01583               {
01584                 currentAnswerResourceNode = response->importNode(currentAnswerResourceNode, true);
01585                 currentAnswerResourceNode->appendChild(
01586                     response->importNode(requestedTranslation->tnc_template, true));
01587                 currentAnswerNode->appendChild(currentAnswerResourceNode);
01588                 validResource = true;
01589               }
01590 
01591               if( getDOMChildByName(requestedResourceItems->item(j), TNC_RESOURCE_CUSTOMIZED_SECT,
01592                           currentAnswerResourceNode, false) == E_SUCCESS)
01593               {
01594                 currentAnswerResourceNode = response->importNode(currentAnswerResourceNode, true);
01595                 currentAnswerResourceNode->appendChild(
01596                     response->importNode(requestedTranslation->tnc_customized, true));
01597                 currentAnswerNode->appendChild(currentAnswerResourceNode);
01598                 validResource = true;
01599               }
01600             }
01601             else
01602             {
01603               CAMsg::printMsg(LOG_DEBUG,"Error: no translation def found.\n");
01604               break;
01605             }
01606           }
01607         }
01608         else
01609         {
01610           CAMsg::printMsg(LOG_DEBUG,"Error: no tc def found.\n");
01611         }
01612       }
01613 
01614       if(!validResource)
01615       {
01616         //only a manipulated client sends an invalid T&C resource request.
01617         //Manipulation is interpreted as a rejection of the terms & conditions,
01618         //so abort login immediately.
01619         response->release();
01620         response = createDOMDocument();
01621         response->appendChild(createDOMElement(response, TNC_RESPONSE_INVALID_REQUEST));
01622         answer->result = TC_FAILED;
01623         break;
01624       }
01625     }
01626     answer->xmlAnswer = response;
01627   }
01628   //Client accepts/rejects the T&Cs.
01629   else if(XMLString::equals(reqName, TNC_CONFIRM))
01630   {
01631     CAMsg::printMsg(LOG_DEBUG,"handling TC confirm.\n");
01632     bool tcAccepted = false;
01633     getDOMElementAttribute(request->getDocumentElement(), "accepted", tcAccepted);
01634     CAMsg::printMsg(LOG_DEBUG,"Client has%s accepted the T&Cs.\n", (tcAccepted ? "" : " not")  );
01635 
01636     answer->xmlAnswer = NULL;
01637     answer->result = tcAccepted ? TC_CONFIRMED : TC_FAILED;
01638   }
01639   //stops the message exchange (if client needs time for showing the T & Cs, etc.)
01640   else if(XMLString::equals(reqName, TNC_INTERRUPT))
01641   {
01642     CAMsg::printMsg(LOG_DEBUG,"client requested interrupting the tc login.\n");
01643     answer->xmlAnswer = NULL;
01644     answer->result = TC_FAILED;
01645   }
01646   //Client sends an invalid message
01647   else
01648   {
01649     answer->xmlAnswer = NULL; //TODO: set errorMessage here
01650     answer->result = TC_FAILED;
01651   }
01652   return answer;
01653 }
01654 
01655 SINT32 CAFirstMix::doUserLogin(CAMuxSocket* pNewUser,UINT8 peerIP[4])
01656 {
01657   INIT_STACK;
01658   SINT32 ret = doUserLogin_internal(pNewUser, peerIP);
01659   FINISH_STACK("CAFirstMix::doUserLogin");
01660   return ret;
01661 }
01662 
01668 SINT32 CAFirstMix::doUserLogin_internal(CAMuxSocket* pNewUser,UINT8 peerIP[4])
01669   {
01670     SINT32 ret;
01671   
01672     INIT_STACK;
01673     BEGIN_STACK("CAFirstMix::doUserLogin");
01674       ret=pNewUser->getCASocket()->setKeepAlive(true);
01675       if(ret!=E_SUCCESS)
01676         CAMsg::printMsg(LOG_DEBUG,"Error setting KeepAlive for user login connection!");
01677 
01678     #ifdef DEBUG
01679       CAMsg::printMsg(LOG_DEBUG,"User login: start\n");
01680     #endif
01681 
01682     SAVE_STACK("CAFirstMix::doUserLogin", "after setting keep alive");
01683 
01684     // send the mix-keys to JAP
01685     if ((ret = pNewUser->getCASocket()->sendFullyTimeOut(m_xmlKeyInfoBuff,m_xmlKeyInfoSize, 40000, 10000)) != E_SUCCESS)
01686     {
01687       if (ret != E_UNKNOWN)
01688       {
01689         CAMsg::printMsg(LOG_DEBUG,"User login: Sending login data to client %u.%u.x.x has been interrupted! Reason: '%s' (%i)\n", 
01690           peerIP[0],peerIP[1], GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
01691       }
01692       else
01693       {
01694         CAMsg::printMsg(LOG_DEBUG,"User login: Sending login data to client %u.%u.x.x has been interrupted!\n", peerIP[0],peerIP[1]);
01695       }
01696 
01697       m_pIPBlockList->insertIP(peerIP);
01698 
01699       delete pNewUser;
01700       pNewUser = NULL;
01701       m_pIPList->removeIP(peerIP);
01702       return E_UNKNOWN;
01703     }
01704     #ifdef DEBUG
01705       CAMsg::printMsg(LOG_DEBUG,"User login: login data sent\n");
01706     #endif
01707     SAVE_STACK("CAFirstMix::doUserLogin", "after sending login data");
01708 
01709     //(pNewUser)->send(m_xmlKeyInfoBuff,m_xmlKeyInfoSize);
01710     // es kann nicht blockieren unter der Annahme das der TCP-Sendbuffer > m_xmlKeyInfoSize ist....
01711 
01712     //wait for keys from user
01713     UINT16 xml_len=0;
01714     if(pNewUser->getCASocket()->isClosed())
01715     {
01716       CAMsg::printMsg(LOG_DEBUG,"User login: Socket was closed while waiting for first symmetric key from client!\n");
01717     }
01718     else if ((ret = pNewUser->getCASocket()->receiveFullyT((UINT8*)&xml_len,2,FIRST_MIX_RECEIVE_SYM_KEY_FROM_JAP_TIME_OUT)) != E_SUCCESS)
01719     {
01720       if (ret != E_UNKNOWN)
01721       {
01722         CAMsg::printMsg(LOG_DEBUG,"User login: Waiting for first symmetric key from client %u.%u.x.x! failed for reason: '%s' (%i)\n", 
01723         peerIP[0], peerIP[1], GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
01724       }
01725       else
01726       {
01727         CAMsg::printMsg(LOG_DEBUG,"User login: Waiting for first symmetric key from client %u.%u.x.x! failed.\n", 
01728           peerIP[0], peerIP[1]);
01729       }
01730       m_pIPBlockList->insertIP(peerIP);
01731       
01732       delete pNewUser;
01733       pNewUser = NULL;
01734       m_pIPList->removeIP(peerIP);
01735       return E_UNKNOWN;
01736     }
01737     #ifdef DEBUG
01738       CAMsg::printMsg(LOG_DEBUG,"User login: received first symmetric key from client\n");
01739     #endif
01740     SAVE_STACK("CAFirstMix::doUserLogin", "received first symmetric key");
01741 
01742     xml_len=ntohs(xml_len);
01743     UINT8* xml_buff=new UINT8[xml_len+2]; //+2 for size...
01744     if(pNewUser->getCASocket()->isClosed() ||
01745        (ret = pNewUser->getCASocket()->receiveFullyT(xml_buff+2,xml_len,FIRST_MIX_RECEIVE_SYM_KEY_FROM_JAP_TIME_OUT)) !=E_SUCCESS)
01746     {
01747       if (pNewUser->getCASocket()->isClosed())
01748       {
01749         SET_NET_ERROR(E_SOCKETCLOSED);
01750       }
01751     
01752 
01753       if (ret != E_UNKNOWN)
01754       {
01755         CAMsg::printMsg(LOG_DEBUG,"User login: Waiting for second symmetric key from client failed for reason: '%s' (%i)\n", 
01756           GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
01757       }
01758       else
01759       {
01760         CAMsg::printMsg(LOG_DEBUG,"User login: Waiting for second symmetric key from client failed.\n");
01761       }
01762 
01763       m_pIPBlockList->insertIP(peerIP);
01764 
01765       delete pNewUser;
01766       pNewUser = NULL;
01767       delete[] xml_buff;
01768       xml_buff = NULL;
01769       m_pIPList->removeIP(peerIP);
01770       return E_UNKNOWN;
01771     }
01772 
01773     #ifdef DEBUG
01774       CAMsg::printMsg(LOG_DEBUG,"User login: received second symmetric key from client\n");
01775     #endif
01776     SAVE_STACK("CAFirstMix::doUserLogin", "received second symmetric key");
01777 
01778     XERCES_CPP_NAMESPACE::DOMDocument* doc=parseDOMDocument(xml_buff+2,xml_len);
01779     DOMElement* elemRoot=NULL;
01780     if(doc==NULL||(elemRoot=doc->getDocumentElement())==NULL||
01781       decryptXMLElement(elemRoot,m_pRSA)!=E_SUCCESS)
01782       {
01783         delete[] xml_buff;
01784         xml_buff = NULL;
01785         delete pNewUser;
01786         pNewUser = NULL;
01787         m_pIPList->removeIP(peerIP);
01788         if(doc!=NULL)
01789         {
01790           doc->release();
01791           doc = NULL;
01792         }
01793         return E_UNKNOWN;
01794       }
01795     elemRoot=doc->getDocumentElement();
01796     if(!equals(elemRoot->getNodeName(),"JAPKeyExchange"))
01797       {
01798         if (doc != NULL)
01799         {
01800           doc->release();
01801           doc = NULL;
01802         }
01803         delete[] xml_buff;
01804         xml_buff = NULL;
01805         delete pNewUser;
01806         pNewUser = NULL;
01807         m_pIPList->removeIP(peerIP);
01808         return E_UNKNOWN;
01809       }
01810     DOMElement* elemLinkEnc=NULL;
01811     DOMElement* elemMixEnc=NULL;
01812     getDOMChildByName(elemRoot,"LinkEncryption",elemLinkEnc,false);
01813     getDOMChildByName(elemRoot,"MixEncryption",elemMixEnc,false);
01814     UINT8 linkKey[255],mixKey[255];
01815     UINT32 linkKeyLen=255,mixKeyLen=255;
01816     if( getDOMElementValue(elemLinkEnc,linkKey,&linkKeyLen)!=E_SUCCESS||
01817         getDOMElementValue(elemMixEnc,mixKey,&mixKeyLen)!=E_SUCCESS||
01818         CABase64::decode(linkKey,linkKeyLen,linkKey,&linkKeyLen)!=E_SUCCESS||
01819         CABase64::decode(mixKey,mixKeyLen,mixKey,&mixKeyLen)!=E_SUCCESS||
01820         linkKeyLen!=64||mixKeyLen!=32)
01821       {
01822         if (doc != NULL)
01823         {
01824           doc->release();
01825           doc = NULL;
01826         }
01827         delete[] xml_buff;
01828         xml_buff = NULL;
01829         delete pNewUser;
01830         pNewUser = NULL;
01831         m_pIPList->removeIP(peerIP);
01832         return E_UNKNOWN;
01833       }
01834     //Getting control channel keys if available
01836     DOMElement* elemControlChannelEnc=NULL;
01837     getDOMChildByName(elemRoot,"ControlChannelEncryption",elemControlChannelEnc,false);
01838     UINT8 controlchannelKey[255];
01839     UINT32 controlchannelKeyLen=255;
01840     UINT8* controlchannelRecvKey=NULL;
01841     UINT8* controlchannelSentKey=NULL;
01842     if( getDOMElementValue(elemControlChannelEnc,controlchannelKey,&controlchannelKeyLen)==E_SUCCESS&&
01843         CABase64::decode(controlchannelKey,controlchannelKeyLen,controlchannelKey,&controlchannelKeyLen)==E_SUCCESS&&
01844         controlchannelKeyLen==32)
01845       {
01846         controlchannelRecvKey=controlchannelKey;
01847         controlchannelSentKey=controlchannelKey+16;
01848       }
01849 
01850     //Sending Signature....
01851     xml_buff[0]=(UINT8)(xml_len>>8);
01852     xml_buff[1]=(UINT8)(xml_len&0xFF);
01853     UINT8* sig=new UINT8[255];
01854     UINT32 siglen=255;
01855     //TODO change me to fully support MultiSig
01856     //m_pSignature->sign(xml_buff,xml_len+2,sig,&siglen);
01857     m_pMultiSignature->sign(xml_buff,xml_len+2,sig,&siglen);
01858     XERCES_CPP_NAMESPACE::DOMDocument* docSig=createDOMDocument();
01859 
01860     DOMElement *elemSig=NULL;
01861 
01862 #ifdef LOG_DIALOG
01863     DOMElement* elemDialog=NULL;
01864     getDOMChildByName(elemRoot,"Dialog",elemDialog,false);
01865     UINT8 strDialog[255];
01866     memset(strDialog,0,255);
01867     UINT32 dialogLen=255;
01868     getDOMElementValue(elemDialog,strDialog,&dialogLen);
01869 #endif
01870 #ifdef REPLAY_DETECTION
01871     //checking if Replay-Detection is enabled
01872     DOMElement *elemReplay=NULL;
01873     UINT8 replay[6];
01874     UINT32 replay_len=5;
01875     if( (getDOMChildByName(elemRoot,"ReplayDetection",elemReplay,false)==E_SUCCESS)&&
01876       (getDOMElementValue(elemReplay,replay,&replay_len)==E_SUCCESS)&&
01877       (strncmp((char*)replay,"true",5)==0)){
01878         elemRoot=createDOMElement(docSig,"MixExchange");
01879         elemReplay=createDOMElement(docSig,"Replay");
01880         docSig->appendChild(elemRoot);
01881         elemRoot->appendChild(elemReplay);
01882 
01883         UINT32 diff=(UINT32)(time(NULL)-m_u64LastTimestampReceived);
01884         for(SINT32 i=0;i<getMixCount()-1;i++)
01885         {
01886           DOMElement* elemMix=createDOMElement(docSig,"Mix");
01887           setDOMElementAttribute(elemMix,"id",m_arMixParameters[i].m_strMixID);
01888           DOMElement* elemReplayOffset=createDOMElement(docSig,"ReplayOffset");
01889           setDOMElementValue(elemReplayOffset,(UINT32) (m_arMixParameters[i].m_u32ReplayOffset+diff));
01890           elemMix->appendChild(elemReplayOffset);
01891           DOMElement* elemReplayBase=createDOMElement(docSig,"ReplayBase");
01892           setDOMElementValue(elemReplayBase,(UINT32) (m_arMixParameters[i].m_u32ReplayBase));
01893           elemMix->appendChild(elemReplayBase);
01894           elemReplay->appendChild(elemMix);
01895         }
01896 
01897         DOMElement* elemMix=createDOMElement(docSig,"Mix");
01898         UINT8 buff[255];
01899         CALibProxytest::getOptions()->getMixId(buff,255);
01900         setDOMElementAttribute(elemMix,"id",buff);
01901         DOMElement* elemReplayOffset=createDOMElement(docSig,"ReplayOffset");
01902         setDOMElementValue(elemReplayOffset,(UINT32) (time(NULL)-m_u64ReferenceTime));
01903         elemMix->appendChild(elemReplayOffset);
01904         DOMElement* elemReplayBase=createDOMElement(docSig,"ReplayBase");
01905         setDOMElementValue(elemReplayBase,(UINT32) (REPLAY_BASE));
01906         elemMix->appendChild(elemReplayOffset);
01907         elemReplay->appendChild(elemMix);
01908 
01909         elemSig=createDOMElement(docSig,"Signature");
01910         elemRoot->appendChild(elemSig);
01911 
01912         CAMsg::printMsg(LOG_DEBUG,"Replay Detection requested\n");
01913         }
01914     else {
01915         elemSig=createDOMElement(docSig,"Signature");
01916         docSig->appendChild(elemSig);
01917       }
01918 #endif
01919 #ifndef REPLAY_DETECTION
01920     elemSig=createDOMElement(docSig,"Signature");
01921     docSig->appendChild(elemSig);
01922 #endif
01923     DOMElement* elemSigValue=createDOMElement(docSig,"SignatureValue");
01924     elemSig->appendChild(elemSigValue);
01925     UINT32 u32=siglen;
01926     CABase64::encode(sig,u32,sig,&siglen);
01927     sig[siglen]=0;
01928     setDOMElementValue(elemSigValue,sig);
01929     delete[] sig;
01930     u32=xml_len;
01931     DOM_Output::dumpToMem(docSig,xml_buff+2,&u32);
01932     if (docSig != NULL)
01933     {
01934       docSig->release();
01935       docSig = NULL;
01936     }
01937     xml_buff[0]=(UINT8)(u32>>8);
01938     xml_buff[1]=(UINT8)(u32&0xFF);
01939 
01940     if (pNewUser->getCASocket()->isClosed() ||
01941         pNewUser->getCASocket()->sendFullyTimeOut(xml_buff,u32+2, 30000, 10000) != E_SUCCESS)
01942     {
01943       if (doc != NULL)
01944       {
01945         doc->release();
01946         doc = NULL;
01947       }
01948       CAMsg::printMsg(LOG_DEBUG,"User login: Sending key exchange signature has been interrupted!\n");
01949       m_pIPBlockList->insertIP(peerIP);
01950       
01951       delete[] xml_buff;
01952       xml_buff = NULL;
01953       delete pNewUser;
01954       pNewUser = NULL;
01955       m_pIPList->removeIP(peerIP);
01956       return E_UNKNOWN;
01957     }
01958     #ifdef DEBUG
01959       CAMsg::printMsg(LOG_DEBUG,"User login: key exchange signature sent\n");
01960     #endif
01961     delete[] xml_buff;
01962     xml_buff = NULL;
01963 #if 0 //terms and conditions sending disabled.
01964     /* handle Terms And Conditions */
01965     bool loginFailed = false;
01966     bool tcProcedureFinished = false;
01967 
01968     while( !(tcProcedureFinished || loginFailed) )
01969     {
01970       UINT16 tcRequestDataLen = 0;
01971       if (pNewUser->getCASocket()->isClosed() ||
01972         (ret = pNewUser->getCASocket()->receiveFullyT((UINT8*)&tcRequestDataLen, 2, 10000)) != E_SUCCESS)
01973       {
01974         if (pNewUser->getCASocket()->isClosed())
01975         {
01976           SET_NET_ERROR(E_SOCKETCLOSED);
01977         }
01978       
01979         loginFailed = true;
01980         if (ret != E_UNKNOWN)
01981         {
01982           CAMsg::printMsg(LOG_ERR,"User login: Receiving t&c protocol data size has been interrupted. Reason: '%s' (%i)\n",
01983             GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
01984         }
01985         else
01986         {
01987           CAMsg::printMsg(LOG_ERR,"User login: Receiving t&c protocol data size has been interrupted.\n");
01988         }
01989         break;
01990       }
01991 
01992       tcRequestDataLen = ntohs(tcRequestDataLen);
01993       //CAMsg::printMsg(LOG_DEBUG,"User login: expecting %u bytes!\n", tcRequestDataLen);
01994       UINT8 tcDataBuf[tcRequestDataLen+1];
01995       tcDataBuf[tcRequestDataLen] = 0;
01996       if (pNewUser->getCASocket()->isClosed() ||
01997         (ret = pNewUser->getCASocket()->receiveFullyT(tcDataBuf, tcRequestDataLen, 10000)) != E_SUCCESS)
01998       {
01999         if (pNewUser->getCASocket()->isClosed())
02000         {
02001           SET_NET_ERROR(E_SOCKETCLOSED);
02002         }
02003         
02004         loginFailed = true;
02005         
02006         if (ret != E_UNKNOWN)
02007         {
02008           CAMsg::printMsg(LOG_ERR,"User login: Receiving t&c protocol data has been interrupted. Reason: '%s' (%i)\n",
02009             GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
02010         }
02011         else
02012         {
02013           CAMsg::printMsg(LOG_ERR,"User login: Receiving t&c protocol data has been interrupted.\n");
02014         }
02015         break;
02016       }
02017 
02018       XERCES_CPP_NAMESPACE::DOMDocument *tcData = parseDOMDocument(tcDataBuf, tcRequestDataLen);
02019       if( (tcData == NULL) || (tcData->getDocumentElement() == NULL) )
02020       {
02021         CAMsg::printMsg(LOG_ERR,"Could not parse t&c data!\n");
02022         loginFailed = true;
02023         break;
02024       }
02025 
02026       termsAndConditionMixAnswer_t *answer = handleTermsAndConditionsLogin(tcData);
02027       if(answer == NULL)
02028       {
02029         loginFailed = true;
02030         tcData->release();
02031         tcData = NULL;
02032         break;
02033       }
02034 
02035       if( (answer->xmlAnswer != NULL) )
02036       {
02037         UINT32 size = 0;
02038         UINT8 *answerBuff = DOM_Output::dumpToMem(answer->xmlAnswer, &size);
02039         if(answerBuff != NULL)
02040         {
02041           //CAMsg::printMsg(LOG_DEBUG,"User login: answer %s\n", answerBuff);
02042 
02043           UINT32 netSize = htonl(size);
02044 
02045           if (pNewUser->getCASocket()->isClosed() ||
02046             pNewUser->getCASocket()->sendFullyTimeOut((UINT8 *) &netSize, 4, 30000, 10000) != E_SUCCESS)
02047           {
02048             CAMsg::printMsg(LOG_DEBUG,"User login: sending t&c protocol data size has been interrupted!\n");
02049             loginFailed = true;
02050           }
02051           else if (pNewUser->getCASocket()->isClosed() ||
02052             pNewUser->getCASocket()->sendFullyTimeOut(answerBuff, size, 30000, 10000) != E_SUCCESS)
02053           {
02054             CAMsg::printMsg(LOG_DEBUG,"User login: Sending t&c protocol data has been interrupted!\n");
02055             loginFailed = true;
02056           }
02057           delete [] answerBuff;
02058         }
02059       }
02060       tcProcedureFinished = (answer->result != TC_UNFINISHED);
02061       loginFailed = (answer->result == TC_FAILED);
02062       cleanupTnCMixAnswer(answer);
02063       delete answer;
02064       answer = NULL;
02065       tcData->release();
02066       tcData = NULL;
02067     }
02068 
02069     //Only if a positive confirm message was received, the client may pass!
02070 
02071     if(loginFailed)
02072     {
02073       if (doc != NULL)
02074       {
02075         doc->release();
02076         doc = NULL;
02077       }
02078       CAMsg::printMsg(LOG_DEBUG,"User login: failed!\n");
02079       delete[] xml_buff;
02080       xml_buff = NULL;
02081       delete pNewUser;
02082       pNewUser = NULL;
02083       m_pIPList->removeIP(peerIP);
02084       return E_UNKNOWN;
02085     }
02086     /* end Terms And Conditions negotiation */
02087 #endif
02088     SAVE_STACK("CAFirstMix::doUserLogin", "sent key exchange signature");
02089 
02090     pNewUser->getCASocket()->setNonBlocking(true);
02091 
02092     SAVE_STACK("CAFirstMix::doUserLogin", "Creating CAQueue...");
02093     CAQueue* tmpQueue=new CAQueue(sizeof(tQueueEntry));
02094 
02095     SAVE_STACK("CAFirstMix::doUserLogin", "Adding user to connection list...");
02096 #ifdef LOG_DIALOG
02097     fmHashTableEntry* pHashEntry=m_pChannelList->add(pNewUser,peerIP,tmpQueue,strDialog);
02098 #else
02099     fmHashTableEntry* pHashEntry=m_pChannelList->add(pNewUser,peerIP,tmpQueue,controlchannelSentKey,controlchannelRecvKey);
02100 #endif
02101     if( (pHashEntry == NULL) ||
02102       (pHashEntry->pControlMessageQueue == NULL) )// adding user connection to mix->JAP channel list (stefan: sollte das nicht connection list sein? --> es handelt sich um eine Datenstruktu fr Connections/Channels ).
02103     {
02104       if (doc != NULL)
02105       {
02106         doc->release();
02107         doc = NULL;
02108       }
02109       CAMsg::printMsg(LOG_ERR,"User login: Could not add new socket to connection list!\n");
02110       if(pHashEntry!=NULL)
02111         m_pChannelList->remove(pNewUser);
02112       m_pIPList->removeIP(peerIP);
02113       delete tmpQueue;
02114       tmpQueue = NULL;
02115       delete pNewUser;
02116       pNewUser = NULL;
02117       return E_UNKNOWN;
02118     }
02119 
02120     SAVE_STACK("CAFirstMix::doUserLogin", "socket added to connection list");
02121 #ifdef PAYMENT
02122     #ifdef DEBUG
02123       CAMsg::printMsg(LOG_DEBUG,"User login: registering payment control channel\n");
02124     #endif
02125     pHashEntry->pControlChannelDispatcher->registerControlChannel(new CAAccountingControlChannel(pHashEntry));
02126     SAVE_STACK("CAFirstMix::doUserLogin", "payment registered");
02127 #endif
02128     pHashEntry->pSymCipher=new CASymCipher();
02129     pHashEntry->pSymCipher->setKey(mixKey);
02130     pHashEntry->pSymCipher->setIVs(mixKey+16);
02131     pNewUser->setReceiveKey(linkKey,32);
02132     pNewUser->setSendKey(linkKey+32,32);
02133     pNewUser->setCrypt(true);
02134 
02135     if (doc != NULL)
02136     {
02137       doc->release();
02138       doc = NULL;
02139     }
02140 #ifdef PAYMENT
02141 
02142     SAVE_STACK("CAFirstMix::doUserLogin", "Starting AI login procedure");
02143 #ifdef DEBUG
02144     CAMsg::printMsg(LOG_DEBUG,"Starting AI login procedure for owner %x \n", pHashEntry);
02145 #endif
02146     SINT32 ai_ret;
02147     MIXPACKET *paymentLoginPacket = new MIXPACKET;
02148     tQueueEntry *aiAnswerQueueEntry=new tQueueEntry;
02149     CAQueue *controlMessages = pHashEntry->pControlMessageQueue;
02150     UINT32 qlen=sizeof(tQueueEntry);
02151     SINT32 aiLoginStatus = 0;
02152     aiLoginStatus = CAAccountingInstance::loginProcessStatus(pHashEntry);
02153     while(aiLoginStatus & AUTH_LOGIN_NOT_FINISHED)
02154     {
02155       if(pNewUser->receive(paymentLoginPacket, AI_LOGIN_SO_TIMEOUT) != MIXPACKET_SIZE)
02156       {
02157         CAMsg::printMsg(LOG_INFO,"AI login: client receive timeout.\n");
02158         aiLoginStatus = AUTH_LOGIN_FAILED;
02159         break;
02160       }
02161       if(paymentLoginPacket->channel > 0 && paymentLoginPacket->channel < 256)
02162       {
02163         if(!pHashEntry->pControlChannelDispatcher->proccessMixPacket(paymentLoginPacket))
02164         {
02165           aiLoginStatus = AUTH_LOGIN_FAILED;
02166           break;
02167         }
02168 
02169         while(controlMessages->getSize()>0)
02170         {
02171           controlMessages->get((UINT8*)aiAnswerQueueEntry,&qlen);
02172           pNewUser->prepareForSend(&(aiAnswerQueueEntry->packet));
02173           ai_ret = pNewUser->getCASocket()->
02174             sendFullyTimeOut(((UINT8*)&(aiAnswerQueueEntry->packet)), MIXPACKET_SIZE, 3*(AI_LOGIN_SO_TIMEOUT), AI_LOGIN_SO_TIMEOUT);
02175           if (ai_ret != E_SUCCESS)
02176           {
02177             if(ai_ret == E_TIMEDOUT )
02178             {
02179               CAMsg::printMsg(LOG_INFO,"timeout occurred during AI login.");
02180             }
02181             aiLoginStatus = AUTH_LOGIN_FAILED;
02182             goto loop_break;
02183           }
02184         }
02185         if(aiLoginStatus == AUTH_LOGIN_FAILED)
02186         {
02187           break;
02188         }
02189       }
02190       aiLoginStatus = CAAccountingInstance::loginProcessStatus(pHashEntry);
02191     }
02192 loop_break:
02193     SAVE_STACK("CAFirstMix::doUserLogin", "AI login packages exchanged.");
02194     /* We have exchanged all AI login packets:
02195      * 1. AccountCert
02196      * 2. ChallengeResponse
02197      * 3. Cost confirmation.
02198      * Now start settlement to ensure that the clients account is balanced
02199      */
02200     if(!(aiLoginStatus & AUTH_LOGIN_FAILED))
02201     {
02202       if(!(aiLoginStatus & (AUTH_LOGIN_SKIP_SETTLEMENT )) || (aiLoginStatus & (AUTH_WAITING_FOR_FIRST_SETTLED_CC)) )
02203       {
02204 //#ifdef DEBUG
02205         CAMsg::printMsg(LOG_DEBUG,"AI login messages successfully exchanged: now starting settlement for user account balancing check\n");
02206 //#endif
02207         if(CAAccountingInstance::newSettlementTransaction() != E_SUCCESS)
02208         {
02209           aiLoginStatus |= AUTH_LOGIN_FAILED;
02210         }
02211       }
02212 //#ifdef DEBUG
02213       else
02214       {
02215         CAMsg::printMsg(LOG_DEBUG,"AI login messages successfully exchanged: skipping settlement, user has valid prepaid amount\n");
02216       }
02217 //#endif
02218     }
02219 
02220     if(!(aiLoginStatus & AUTH_LOGIN_FAILED))
02221     {
02222       aiLoginStatus = CAAccountingInstance::finishLoginProcess(pHashEntry);
02223       if(pNewUser != NULL)
02224       {
02225         while(controlMessages->getSize()>0)
02226         {
02227           controlMessages->get((UINT8*)aiAnswerQueueEntry,&qlen);
02228           pNewUser->prepareForSend(&(aiAnswerQueueEntry->packet));
02229 
02230           //not really elegant but works: if the client closed the socket during the settlement
02231           //the first send will succeed but the second one will fail.
02232           ai_ret = pNewUser->getCASocket()->
02233               sendFullyTimeOut(((UINT8*)&(aiAnswerQueueEntry->packet)), 499, 3*(AI_LOGIN_SO_TIMEOUT), AI_LOGIN_SO_TIMEOUT);
02234 
02235           ai_ret =  pNewUser->getCASocket()->
02236               sendFullyTimeOut(((UINT8*)&(aiAnswerQueueEntry->packet)+499), 499, 3*(AI_LOGIN_SO_TIMEOUT), AI_LOGIN_SO_TIMEOUT);
02237           if (ai_ret != E_SUCCESS)
02238           {
02239             int errnum = errno;
02240             CAMsg::printMsg(LOG_INFO,"AI login: net error occured after settling: %s\n", strerror(errnum));
02241             aiLoginStatus |= AUTH_LOGIN_FAILED;
02242             break;
02243           }
02244         }
02245       }
02246       else
02247       {
02248         CAMsg::printMsg(LOG_DEBUG,"Socket was disposed.\n");
02249         aiLoginStatus |= AUTH_LOGIN_FAILED;
02250       }
02251     }
02252 
02253     delete paymentLoginPacket;
02254     paymentLoginPacket = NULL;
02255     delete aiAnswerQueueEntry;
02256     aiAnswerQueueEntry = NULL;
02257 
02258     SAVE_STACK("CAFirstMix::doUserLogin", "AI login procedure finished.");
02259 
02260     if((aiLoginStatus & AUTH_LOGIN_FAILED))
02261     {
02262 #ifdef DEBUG
02263       CAMsg::printMsg(LOG_INFO,"User AI login failed: deleting socket %x\n", pHashEntry);
02264 #endif
02265       CAAccountingInstance::unlockLogin(pHashEntry);
02266       m_pChannelList->remove(pNewUser);
02267       delete pNewUser;
02268       pNewUser = NULL;
02269       m_pIPList->removeIP(peerIP);
02270       return E_UNKNOWN;
02271     }
02272     /* Hot fix: push timeout entry only if login was succesful, otherwise
02273      * socket may be deleted due to timeout, login fails and the socket will be deleted
02274      * for second time causing a segfault.
02275      */
02276     m_pChannelList->pushTimeoutEntry(pHashEntry);
02277     
02278     
02279 #ifdef LOG_CRIME
02280     UINT64 accountNumber = CAAccountingInstance::unlockLogin(pHashEntry);
02281     UINT64* surveillanceAccounts = CALibProxytest::getOptions()->getCrimeSurveillanceAccounts();
02282     UINT32 nrOfSurveillanceAccounts = CALibProxytest::getOptions()->getNrOfCrimeSurveillanceAccounts();
02283     
02284     for (UINT32 iAccount = 0; iAccount < nrOfSurveillanceAccounts; iAccount++)
02285     {
02286       if (accountNumber == surveillanceAccounts[iAccount])
02287       {
02288         CAMsg::printMsg(LOG_CRIT,"Crime detection: User logged in with account %llu has IP %u.%u.%u.%u\n",accountNumber, peerIP[0], peerIP[1], peerIP[2], peerIP[3]);
02289         break;
02290       }
02291     }
02292 #else
02293     CAAccountingInstance::unlockLogin(pHashEntry);
02294 #endif
02295     
02296 #ifdef DEBUG
02297     CAMsg::printMsg(LOG_INFO,"User AI login successful for owner %x\n", pHashEntry);
02298 #endif
02299 #endif
02300 
02301 #ifdef WITH_CONTROL_CHANNELS_TEST
02302     pHashEntry->pControlChannelDispatcher->registerControlChannel(new CAControlChannelTest());
02303 #endif
02304 #ifdef REPLAY_DETECTION
02305     pHashEntry->pControlChannelDispatcher->registerControlChannel(new CAReplayControlChannel(m_pReplayMsgProc));
02306 #endif
02307 #ifdef COUNTRY_STATS
02308     incUsers(pHashEntry);
02309 #else
02310     incUsers();
02311 #endif
02312 #ifdef HAVE_EPOLL
02313     m_psocketgroupUsersRead->add(*pNewUser,m_pChannelList->get(pNewUser)); // add user socket to the established ones that we read data from.
02314     m_psocketgroupUsersWrite->add(*pNewUser,m_pChannelList->get(pNewUser));
02315 #else
02316     if(m_psocketgroupUsersRead->add(*pNewUser)!=E_SUCCESS)// add user socket to the established ones that we read data from.
02317     {
02318       CAMsg::printMsg(LOG_DEBUG,"User login: Adding to m_psocketgroupUsersRead failed!\n");
02319     }
02320     if( m_psocketgroupUsersWrite->add(*pNewUser)!=E_SUCCESS)
02321     {
02322       CAMsg::printMsg(LOG_DEBUG,"User login: Adding to m_psocketgroupUsersWrite failed!\n");
02323     }
02324 #endif
02325 
02326 #ifndef LOG_DIALOG
02327     CAMsg::printMsg(LOG_INFO,"User login: finished\n");
02328 #else
02329     CAMsg::printMsg(LOG_INFO,"User login: finished -- connection-ID: %Lu -- country-id: %u -- dialog: %s\n",pHashEntry->id,pHashEntry->countryID,pHashEntry->strDialog);
02330 #endif
02331     return E_SUCCESS;
02332   }
02333 
02334 #ifdef PAYMENT
02335 bool CAFirstMix::forceKickout(fmHashTableEntry* pHashTableEntry, const XERCES_CPP_NAMESPACE::DOMDocument *pErrDoc)
02336 {
02337   return m_pChannelList->forceKickout(pHashTableEntry, pErrDoc);
02338 }
02339 #endif
02340 //NEVER EVER DELETE THIS!
02341 /*
02342 THREAD_RETURN loopReadFromUsers(void* param)
02343   {
02344     CAFirstMix* pFirstMix=(CAFirstMix*)param;
02345     CAFirstMixChannelList* pChannelList=pFirstMix->m_pChannelList;
02346     CASocketGroup* psocketgroupUsersRead=pFirstMix->m_psocketgroupUsersRead;
02347     CASocketGroup* psocketgroupUsersWrite=pFirstMix->m_psocketgroupUsersWrite;
02348     CAQueue* pQueueSendToMix=pFirstMix->m_pQueueSendToMix;
02349 //    CAInfoService* pInfoService=pFirstMix->m_pInfoService;
02350     CAASymCipher* pRSA=pFirstMix->m_pRSA;
02351     CAIPList* pIPList=pFirstMix->m_pIPList;
02352     CAMuxSocket* pNextMix=pFirstMix->m_pMuxOut;
02353 
02354     CAMuxSocket* pMuxSocket;
02355 
02356     SINT32 countRead;
02357     SINT32 ret;
02358     UINT8* ip=new UINT8[4];
02359     UINT8* tmpBuff=new UINT8[MIXPACKET_SIZE];
02360     MIXPACKET* pMixPacket=new MIXPACKET;
02361     UINT8* rsaBuff=new UINT8[RSA_SIZE];
02362 
02363     fmHashTableEntry* pHashEntry;
02364     fmChannelListEntry* pEntry;
02365     CASymCipher* pCipher=NULL;
02366 
02367     for(;;)
02368       {
02369         countRead=psocketgroupUsersRead->select(false,1000); //if we sleep here forever, we will not notice new sockets...
02370         if(countRead<0)
02371           { //check for error
02372             if(pFirstMix->m_bRestart ||countRead!=E_TIMEDOUT)
02373               goto END_THREAD;
02374           }
02375         pHashEntry=pChannelList->getFirst();
02376         while(pHashEntry!=NULL&&countRead>0)
02377           {
02378             pMuxSocket=pHashEntry->pMuxSocket;
02379             if(psocketgroupUsersRead->isSignaled(*pMuxSocket))
02380               {
02381                 countRead--;
02382                 ret=pMuxSocket->receive(pMixPacket,0);
02383                 if(ret==SOCKET_ERROR)
02384                   {
02385                     pMuxSocket->getPeerIP(ip);
02386                     pIPList->removeIP(ip);
02387                     psocketgroupUsersRead->remove(pMuxSocket);
02388                     psocketgroupUsersWrite->remove(pMuxSocket);
02389                     pEntry=pChannelList->getFirstChannelForSocket(pMuxSocket);
02390                     while(pEntry!=NULL)
02391                       {
02392                         pNextMix->close(pEntry->channelOut,tmpBuff);
02393                         pQueueSendToMix->add(tmpBuff,MIXPACKET_SIZE);
02394                         delete pEntry->pCipher;
02395                         pEntry=pChannelList->getNextChannel(pEntry);
02396                       }
02397                     ASSERT(pHashEntry->pQueueSend!=NULL,"Send queue is NULL");
02398                     delete pHashEntry->pQueueSend;
02399                     pChannelList->remove(pMuxSocket);
02400                     pMuxSocket->close();
02401                     delete pMuxSocket;
02402                     pFirstMix->decUsers();
02403                   }
02404                 else if(ret==MIXPACKET_SIZE)
02405                   {
02406                     if(pMixPacket->flags==CHANNEL_CLOSE)
02407                       {
02408                         pEntry=pChannelList->get(pMuxSocket,pMixPacket->channel);
02409                         if(pEntry!=NULL)
02410                           {
02411                             pNextMix->close(pEntry->channelOut,tmpBuff);
02412                             pQueueSendToMix->add(tmpBuff,MIXPACKET_SIZE);
02413                             delete pEntry->pCipher;
02414                             pChannelList->removeChannel(pMuxSocket,pMixPacket->channel);
02415                           }
02416                         else
02417                           {
02418                             #if defined(_DEBUG) && ! defined(__MIX_TEST)
02419                               CAMsg::printMsg(LOG_DEBUG,"Invalid ID to close from Browser!\n");
02420                             #endif
02421                           }
02422                       }
02423                     else
02424                       {
02425                         pEntry=pChannelList->get(pMuxSocket,pMixPacket->channel);
02426                         if(pEntry!=NULL&&pMixPacket->flags==CHANNEL_DATA)
02427                           {
02428                             pMixPacket->channel=pEntry->channelOut;
02429                             pCipher=pEntry->pCipher;
02430                             pCipher->decryptAES(pMixPacket->data,pMixPacket->data,DATA_SIZE);
02431                             pNextMix->send(pMixPacket,tmpBuff);
02432                             pQueueSendToMix->add(tmpBuff,MIXPACKET_SIZE);
02433                             pFirstMix->incMixedPackets();
02434                           }
02435                         else if(pEntry==NULL&&(pMixPacket->flags==CHANNEL_OPEN_OLD||pMixPacket->flags==CHANNEL_OPEN_NEW))
02436                           {
02437                             pCipher= new CASymCipher();
02438                             pRSA->decrypt(pMixPacket->data,rsaBuff);
02439                             pCipher->setKeyAES(rsaBuff);
02440                             pCipher->decryptAES(pMixPacket->data+RSA_SIZE,
02441                                              pMixPacket->data+RSA_SIZE-KEY_SIZE,
02442                                              DATA_SIZE-RSA_SIZE);
02443                             memcpy(pMixPacket->data,rsaBuff+KEY_SIZE,RSA_SIZE-KEY_SIZE);
02444 
02445                             if(pChannelList->addChannel(pMuxSocket,pMixPacket->channel,pCipher,&pMixPacket->channel)!=E_SUCCESS)
02446                               {//todo --> maybe move up to not make decryption!!
02447                                 delete pCipher;
02448                               }
02449                             else
02450                               {
02451                                 #if defined(_DEBUG) && !defined(__MIX_TEST)
02452                                   CAMsg::printMsg(LOG_DEBUG,"Added out channel: %u\n",pMixPacket->channel);
02453                                 #endif
02454                                 pNextMix->send(pMixPacket,tmpBuff);
02455                                 pQueueSendToMix->add(tmpBuff,MIXPACKET_SIZE);
02456                                 pFirstMix->incMixedPackets();
02457                               }
02458                           }
02459                       }
02460                   }
02461               }
02462             pHashEntry=pChannelList->getNext();
02463           }
02464       }
02465 END_THREAD:
02466     delete ip;
02467     delete tmpBuff;
02468     delete pMixPacket;
02469     delete rsaBuff;
02470     CAMsg::printMsg(LOG_DEBUG,"Exiting Thread ReadFromUser\n");
02471     THREAD_RETURN_SUCCESS;
02472   }
02473 */
02474 
02475 SINT32 CAFirstMix::clean()
02476   {
02477     //#ifdef _DEBUG
02478       CAMsg::printMsg(LOG_DEBUG,"CAFirstMix::clean() start\n");
02479     //#endif
02480     m_bRunLog=false;
02481     m_bRestart=true;
02482     if(m_pMuxOut!=NULL)
02483       {
02484         m_pMuxOut->close();
02485       }
02486 
02487     //writing some bytes to the queue...
02488     if(m_pQueueSendToMix!=NULL)
02489       {
02490         UINT8 b[sizeof(tQueueEntry)+1];
02491         m_pQueueSendToMix->add(b,sizeof(tQueueEntry)+1);
02492       }
02493 
02494     if(m_pthreadAcceptUsers!=NULL)
02495         {
02496           CAMsg::printMsg(LOG_CRIT,"Wait for LoopAcceptUsers!\n");
02497           m_pthreadAcceptUsers->join();
02498           delete m_pthreadAcceptUsers;
02499         }
02500     m_pthreadAcceptUsers=NULL;
02501     if(m_pthreadsLogin!=NULL)
02502       delete m_pthreadsLogin;
02503     m_pthreadsLogin=NULL;
02504     //     if(m_pInfoService!=NULL)
02505     //     {
02506     //         CAMsg::printMsg(LOG_CRIT,"Stopping InfoService....\n");
02507     //         CAMsg::printMsg  (LOG_CRIT,"Memory usage before: %u\n",getMemoryUsage());
02508     //         m_pInfoService->stop();
02509     //         CAMsg::printMsg  (LOG_CRIT,"Memory usage after: %u\n",getMemoryUsage());
02510     //         CAMsg::printMsg(LOG_CRIT,"Stopped InfoService!\n");
02511     //         delete m_pInfoService;
02512     //     }
02513     //     m_pInfoService=NULL;
02514 
02515   if(m_pthreadSendToMix!=NULL)
02516     {
02517       CAMsg::printMsg(LOG_CRIT,"Wait for LoopSendToMix!\n");
02518       m_pthreadSendToMix->join();
02519       delete m_pthreadSendToMix;
02520     }
02521   m_pthreadSendToMix=NULL;
02522   if(m_pthreadReadFromMix!=NULL)
02523     {
02524       CAMsg::printMsg(LOG_CRIT,"Wait for LoopReadFromMix!\n");
02525       m_pthreadReadFromMix->join();
02526       delete m_pthreadReadFromMix;
02527     }
02528   m_pthreadReadFromMix=NULL;
02529 
02530 #ifdef CH_LOG_STUDY
02531   if(nrOfChThread != NULL)
02532   {
02533     nrOfChThread->join();
02534     delete nrOfChThread;
02535     nrOfChThread = NULL;
02536   }
02537 #endif
02538 
02539 #ifdef LOG_PACKET_TIMES
02540     if(m_pLogPacketStats!=NULL)
02541       {
02542         CAMsg::printMsg(LOG_CRIT,"Wait for LoopLogPacketStats to terminate!\n");
02543         m_pLogPacketStats->stop();
02544         delete m_pLogPacketStats;
02545       }
02546     m_pLogPacketStats=NULL;
02547 #endif
02548     if(m_arrSocketsIn!=NULL)
02549       {
02550         for(UINT32 i=0;i<m_nSocketsIn;i++)
02551         {
02552           if (m_arrSocketsIn[i] != NULL)
02553           {
02554             m_arrSocketsIn[i]->close();
02555             delete m_arrSocketsIn[i];
02556             m_arrSocketsIn[i] = NULL;
02557           }
02558         }
02559         delete[] m_arrSocketsIn;
02560       }
02561     m_arrSocketsIn=NULL;
02562 #ifdef REPLAY_DETECTION
02563     if(m_pReplayMsgProc!=NULL)
02564       {
02565         delete m_pReplayMsgProc;
02566       }
02567     m_pReplayMsgProc=NULL;
02568 #endif
02569 
02570     if(m_pMuxOutControlChannelDispatcher!=NULL)
02571     {
02572       delete m_pMuxOutControlChannelDispatcher;
02573     }
02574     m_pMuxOutControlChannelDispatcher=NULL;
02575 
02576     if(m_pMuxOut!=NULL)
02577       {
02578         m_pMuxOut->close();
02579         delete m_pMuxOut;
02580       }
02581     m_pMuxOut=NULL;
02582 #ifdef COUNTRY_STATS
02583     deleteCountryStats();
02584 #endif
02585     if(m_pIPList!=NULL)
02586       delete m_pIPList;
02587     m_pIPList=NULL;
02588     if(m_pQueueSendToMix!=NULL)
02589       delete m_pQueueSendToMix;
02590     m_pQueueSendToMix=NULL;
02591     if(m_pQueueReadFromMix!=NULL)
02592       delete m_pQueueReadFromMix;
02593     m_pQueueReadFromMix=NULL;
02594 
02595     if(m_pChannelList!=NULL)
02596       {
02597         CAMsg::printMsg(LOG_CRIT,"Before deleting CAFirstMixChannelList()!\n");
02598         CAMsg::printMsg (LOG_CRIT,"Memory usage before: %u\n",getMemoryUsage());
02599         fmHashTableEntry* pHashEntry=m_pChannelList->getFirst();
02600         while(pHashEntry!=NULL)
02601           {
02602             CAMuxSocket * pMuxSocket=pHashEntry->pMuxSocket;
02603             delete pHashEntry->pQueueSend;
02604             pHashEntry->pQueueSend = NULL;
02605             delete pHashEntry->pSymCipher;
02606             pHashEntry->pSymCipher = NULL;
02607 
02608             fmChannelListEntry* pEntry=m_pChannelList->getFirstChannelForSocket(pHashEntry->pMuxSocket);
02609             while(pEntry!=NULL)
02610               {
02611                 delete pEntry->pCipher;
02612                 pEntry->pCipher = NULL;
02613                 pEntry=m_pChannelList->getNextChannel(pEntry);
02614               }
02615             m_pChannelList->remove(pHashEntry->pMuxSocket);
02616             pMuxSocket->close();
02617             delete pMuxSocket;
02618             pMuxSocket = NULL;
02619             pHashEntry=m_pChannelList->getNext();
02620           }
02621       }
02622 
02623     if(m_pChannelList!=NULL)
02624       delete m_pChannelList;
02625     m_pChannelList=NULL;
02626     CAMsg::printMsg (LOG_CRIT,"Memory usage after: %u\n",getMemoryUsage());
02627 #ifdef PAYMENT
02628   CAAccountingInstance::clean();
02629   CAAccountingDBInterface::cleanup();
02630 #endif
02631     if(m_psocketgroupUsersRead!=NULL)
02632       delete m_psocketgroupUsersRead;
02633     m_psocketgroupUsersRead=NULL;
02634     if(m_psocketgroupUsersWrite!=NULL)
02635       delete m_psocketgroupUsersWrite;
02636     m_psocketgroupUsersWrite=NULL;
02637     if(m_pRSA!=NULL)
02638       delete m_pRSA;
02639     m_pRSA=NULL;
02640     if(m_xmlKeyInfoBuff!=NULL)
02641       delete[] m_xmlKeyInfoBuff;
02642     m_xmlKeyInfoBuff=NULL;
02643     m_docMixCascadeInfo=NULL;
02644     if(m_arMixParameters!=NULL)
02645     {
02646       for(UINT32 i=0;i<m_u32MixCount-1;i++)
02647         {
02648           delete[] m_arMixParameters[i].m_strMixID;
02649         }
02650       delete[] m_arMixParameters;
02651     }
02652     m_arMixParameters=NULL;
02653     m_u32MixCount=0;
02654     m_nMixedPackets=0; //reset to zero after each restart (at the moment neccessary for infoservice)
02655     m_nUser=0;
02656 
02657 
02658     delete m_pIPBlockList;
02659     m_pIPBlockList = NULL;
02660 
02661     CAMsg::printMsg (LOG_CRIT,"before tc cleanup\n");
02662     for (UINT32 i = 0; i < m_nrOfTermsAndConditionsDefs; i++)
02663     {
02664       delete m_tnCDefs[i];
02665       m_tnCDefs[i] = NULL;
02666     }
02667     delete [] m_tnCDefs;
02668     m_tnCDefs = NULL;
02669     m_nrOfTermsAndConditionsDefs = 0;
02670     CAMsg::printMsg (LOG_CRIT,"before template cleanup\n");
02671     for(UINT32 i = 0; i < m_nrOfTermsAndConditionsTemplates; i++)
02672     {
02673       m_tcTemplates[i]->release();
02674       m_tcTemplates[i] = NULL;
02675     }
02676     delete [] m_tcTemplates;
02677     m_tcTemplates = NULL;
02678     CAMsg::printMsg (LOG_CRIT,"before template owner release\n");
02679     if(m_templatesOwner != NULL)
02680     {
02681       m_templatesOwner->release();
02682       m_templatesOwner = NULL;
02683     }
02684     CAMsg::printMsg (LOG_CRIT,"after template owner release\n");
02685     m_nrOfTermsAndConditionsTemplates = 0;
02686     //#ifdef _DEBUG
02687       CAMsg::printMsg(LOG_DEBUG,"CAFirstMix::clean() finished\n");
02688     //#endif
02689 
02690     return E_SUCCESS;
02691   }
02692 
02693 #ifdef DELAY_USERS
02694 SINT32 CAFirstMix::reconfigure()
02695   {
02696     CAMsg::printMsg(LOG_DEBUG,"Reconfiguring First Mix\n");
02697 #ifdef DELAY_USERS
02698     CAMsg::printMsg(LOG_DEBUG,"Set new ressources limitation parameters\n");
02699     if(m_pChannelList!=NULL)
02700       m_pChannelList->setDelayParameters( CALibProxytest::getOptions()->getDelayChannelUnlimitTraffic(),
02701                                           CALibProxytest::getOptions()->getDelayChannelBucketGrow(),
02702                                           CALibProxytest::getOptions()->getDelayChannelBucketGrowIntervall());
02703 #endif
02704     return E_SUCCESS;
02705   }
02706 #endif
02707 
02709 SINT32 CAFirstMix::initMixParameters(DOMElement*  elemMixes)
02710   {
02711     DOMNodeList* nl=getElementsByTagName(elemMixes,"Mix");
02712     m_u32MixCount=nl->getLength();
02713     m_arMixParameters=new tMixParameters[m_u32MixCount];
02714     memset(m_arMixParameters,0,sizeof(tMixParameters)*m_u32MixCount);
02715     UINT8 buff[255];
02716     CALibProxytest::getOptions()->getMixId(buff,255);
02717     UINT32 len=strlen((char*)buff)+1;
02718     UINT32 aktMix=0;
02719     for(UINT32 i=0;i<nl->getLength();i++)
02720     {
02721       DOMNode* child=nl->item(i);
02722       len=255;
02723       getDOMElementAttribute(child,"id",buff,&len);
02724       m_arMixParameters[aktMix].m_strMixID=new UINT8[len+1];
02725       memcpy(m_arMixParameters[aktMix].m_strMixID,buff,len);
02726       m_arMixParameters[aktMix].m_strMixID[len]=0;
02727       aktMix++;
02728     }
02729     m_u32MixCount++;
02730     return E_SUCCESS;
02731   }
02732 
02733 UINT32 CAFirstMix::getNrOfUsers()
02734 {
02735   #ifdef PAYMENT
02736   return CAAccountingInstance::getNrOfUsers();
02737   #else
02738   return m_nUser;
02739   #endif
02740 }
02741 
02742 SINT32 CAFirstMix::getMixedPackets(UINT64& ppackets)
02743 {
02744   set64(ppackets,m_nMixedPackets);
02745   return E_SUCCESS;
02746 }
02747 
02748 SINT32 CAFirstMix::getLevel(SINT32* puser,SINT32* prisk,SINT32* ptraffic)
02749 {
02750   *puser=(SINT32)getNrOfUsers();
02751   *prisk=-1;
02752   *ptraffic=-1;
02753   return E_SUCCESS;
02754 }
02755 
02756 #ifdef REPLAY_DETECTION
02757 SINT32 CAFirstMix::sendReplayTimestampRequestsToAllMixes()
02758   {
02759     for(UINT32 i=0;i<m_u32MixCount-1;i++)
02760       {
02761         m_pReplayMsgProc->sendGetTimestamp(m_arMixParameters[i].m_strMixID);
02762       }
02763     return E_SUCCESS;
02764   }
02765 #endif //REPLAY_DETECTION
02766 
02767 #ifdef COUNTRY_STATS
02768 #define COUNTRY_STATS_DB "CountryStats"
02769 #define NR_OF_COUNTRIES 254
02770 
02773 void mysqlEscapeTableName(UINT8* str)
02774   {
02775     UINT32 i=0;
02776     while(str[i]!=0)
02777       {
02778         if(str[i]=='.'||str[i]==':'||str[i]=='/'||str[i]=='\\')
02779           str[i]='_';
02780         i++;
02781       }
02782   }
02783 
02784 SINT32 CAFirstMix::initCountryStats(char* db_host,char* db_user,char* db_passwd)
02785   {
02786     m_CountryStats=NULL;
02787     m_mysqlCon=mysql_init(NULL);
02788 #ifdef HAVE_MYSQL_OPT_RECONNECT
02789     my_bool thetrue=1;
02790     mysql_options(m_mysqlCon,MYSQL_OPT_RECONNECT,&thetrue);
02791 #endif
02792     MYSQL* tmp=NULL;
02793     tmp=mysql_real_connect(m_mysqlCon,db_host,db_user,db_passwd,COUNTRY_STATS_DB,0,NULL,0);
02794     if(tmp==NULL)
02795       {
02796         CAMsg::printMsg(LOG_DEBUG,"Could not connect to CountryStats DB!\n");
02797         mysql_thread_end();
02798         mysql_close(m_mysqlCon);
02799         m_mysqlCon=NULL;
02800         return E_UNKNOWN;
02801       }
02802     CAMsg::printMsg(LOG_DEBUG,"Connected to CountryStats DB!\n");
02803     char query[1024];
02804     UINT8 buff[255];
02805     CALibProxytest::getOptions()->getCascadeName(buff,255);
02806     mysqlEscapeTableName(buff);
02807     sprintf(query,"CREATE TABLE IF NOT EXISTS `stats_%s` (date timestamp,id int,count int,packets_in int,packets_out int)",buff);
02808     SINT32 ret=mysql_query(m_mysqlCon,query);
02809     if(ret!=0)
02810     {
02811         CAMsg::printMsg(LOG_INFO,"CountryStats DB - create table for %s failed!\n",buff);
02812     }
02813     m_CountryStats=new UINT32[NR_OF_COUNTRIES+1];
02814     memset((void*)m_CountryStats,0,sizeof(UINT32)*(NR_OF_COUNTRIES+1));
02815     m_PacketsPerCountryIN=new tUINT32withLock[NR_OF_COUNTRIES+1];
02816     //memset((void*)m_PacketsPerCountryIN,0,sizeof(UINT32)*(NR_OF_COUNTRIES+1));
02817     m_PacketsPerCountryOUT=new tUINT32withLock[NR_OF_COUNTRIES+1];
02818     //memset((void*)m_PacketsPerCountryOUT,0,sizeof(UINT32)*(NR_OF_COUNTRIES+1));
02819     m_threadLogLoop=new CAThread((UINT8*)"Country Logger Thread");
02820     m_threadLogLoop->setMainLoop(iplist_loopDoLogCountries);
02821     m_bRunLogCountries=true;
02822     m_threadLogLoop->start(this,true);
02823     return E_SUCCESS;
02824   }
02825 
02826 SINT32 CAFirstMix::deleteCountryStats()
02827   {
02828     m_bRunLogCountries=false;
02829     if(m_threadLogLoop!=NULL)
02830       {
02831         m_threadLogLoop->join();
02832         delete m_threadLogLoop;
02833         m_threadLogLoop=NULL;
02834       }
02835     if(m_mysqlCon!=NULL)
02836       {
02837         mysql_thread_end();
02838         mysql_close(m_mysqlCon);
02839         m_mysqlCon=NULL;
02840       }
02841 
02842     delete[] m_CountryStats;
02843     m_CountryStats=NULL;
02844 
02845     delete[] m_PacketsPerCountryIN;
02846     m_PacketsPerCountryIN=NULL;
02847 
02848     delete[] m_PacketsPerCountryOUT;
02849     m_PacketsPerCountryOUT=NULL;
02850     return E_SUCCESS;
02851   }
02852 
02861 SINT32 CAFirstMix::updateCountryStats(const UINT8 ip[4],UINT32 a_countryID,bool bRemove)
02862   {
02863     if(!bRemove)
02864       {
02865         UINT32 countryID=a_countryID;
02866         if(ip!=NULL)
02867           {
02868             UINT32 u32ip=ip[0]<<24|ip[1]<<16|ip[2]<<8|ip[3];
02869             char query[1024];
02870             sprintf(query,"SELECT id FROM ip2c WHERE ip_lo<=\"%u\" and ip_hi>=\"%u\" LIMIT 1",u32ip,u32ip);
02871             int ret=mysql_query(m_mysqlCon,query);
02872             if(ret!=0)
02873               {
02874                 CAMsg::printMsg(LOG_INFO,"CountryStatsDB - updateCountryStats - error (%i) in finding countryid for ip %u\n",ret,u32ip);
02875                 goto RET;
02876               }
02877             MYSQL_RES* result=mysql_store_result(m_mysqlCon);
02878             if(result==NULL)
02879               {
02880                 CAMsg::printMsg(LOG_INFO,"CountryStatsDB - updateCountryStats - error in retriving results of the query\n");
02881                 goto RET;
02882               }
02883             MYSQL_ROW row=mysql_fetch_row(result);
02884             SINT32 t;
02885             if(row!=NULL&&(t=atoi(row[0]))>0&&t<=NR_OF_COUNTRIES)
02886               {
02887                 countryID=t;
02888                 #ifdef DEBUG
02889                   CAMsg::printMsg(LOG_DEBUG,"Country ID for ip %u is %u\n",u32ip,countryID);
02890                 #endif
02891                 //temp hack
02892                 if(countryID==99)
02893                 {
02894                   CAMsg::printMsg(LOG_DEBUG,"Country ID for ip %u.%u.%u.%u is %u\n",ip[0],ip[1],ip[2],ip[3],countryID);
02895                 }
02896               }
02897             else
02898               {
02899                 CAMsg::printMsg(LOG_DEBUG,"DO country stats query result no result for ip %u)\n",u32ip);
02900               }
02901             mysql_free_result(result);
02902           }
02903 RET:
02904         m_CountryStats[countryID]++;
02905         return countryID;
02906       }
02907     else//bRemove
02908       {
02909         m_CountryStats[a_countryID]--;
02910       }
02911     return a_countryID;
02912   }
02913 
02914 THREAD_RETURN iplist_loopDoLogCountries(void* param)
02915   {
02916     mysql_thread_init();
02917     CAMsg::printMsg(LOG_DEBUG,"Starting iplist_loopDoLogCountries\n");
02918     CAFirstMix* pFirstMix=(CAFirstMix*)param;
02919     UINT32 s=0;
02920     UINT8 buff[255];
02921     memset(buff,0,255);
02922     CALibProxytest::getOptions()->getCascadeName(buff,255);
02923     mysqlEscapeTableName(buff);
02924     while(pFirstMix->m_bRunLogCountries)
02925       {
02926         if(s==LOG_COUNTRIES_INTERVALL)
02927           {
02928             UINT8 aktDate[255];
02929             time_t aktTime=time(NULL);
02930             strftime((char*)aktDate,255,"%Y%m%d%H%M%S",gmtime(&aktTime));
02931             char query[1024];
02932             sprintf(query,"INSERT into `stats_%s` (date,id,count,packets_in,packets_out) VALUES (\"%s\",\"%%u\",\"%%u\",\"%%u\",\"%%u\")",buff,aktDate);
02933             pFirstMix->m_pmutexUser->lock();
02934             for(UINT32 i=0;i<NR_OF_COUNTRIES+1;i++)
02935               {
02936                 if(pFirstMix->m_CountryStats[i]>0)
02937                   {
02938                     char aktQuery[1024];
02939                     sprintf(aktQuery,query,i,pFirstMix->m_CountryStats[i],pFirstMix->m_PacketsPerCountryIN[i].getAndzero(),pFirstMix->m_PacketsPerCountryOUT[i].getAndzero());
02940                     SINT32 ret=mysql_query(pFirstMix->m_mysqlCon,aktQuery);
02941                     if(ret!=0)
02942                     {
02943                       CAMsg::printMsg(LOG_INFO,"CountryStats DB - failed to update CountryStats DB with new values - error %i\n",ret);
02944                     }
02945                   }
02946               }
02947             pFirstMix->m_pmutexUser->unlock();
02948             s=0;
02949           }
02950         sSleep(10);
02951         s++;
02952       }
02953     CAMsg::printMsg(LOG_DEBUG,"Exiting iplist_loopDoLogCountries\n");
02954     mysql_thread_end();
02955     THREAD_RETURN_SUCCESS;
02956   }
02957 #endif
02958 #endif //ONLY_LOCAL_PROXY