anon-proxy-00.05.38+20081230/0000755000175000017500000000000011126611775013723 5ustar daviddavidanon-proxy-00.05.38+20081230/CAReplayCtrlChannelMsgProc.hpp0000644000175000017500000001052010776710435021506 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef CA_REPLAY_CONTROL_CHANNEL_MSG_PROC #define CA_REPLAY_CONTROL_CHANNEL_MSG_PROC #include "CAThread.hpp" class CAMix; class CAMixWithReplayDB; class CAReplayControlChannel; THREAD_RETURN rp_loopPropagateTimestamp(void* param); class CAReplayCtrlChannelMsgProc { public: /** Initialises the replay control channel messages processor with the necessary information.*/ CAReplayCtrlChannelMsgProc(const CAMixWithReplayDB* pMix); ~CAReplayCtrlChannelMsgProc(); /** Propagates downstream the current replay timestamp*/ SINT32 propagateCurrentReplayTimestamp(); /** Sends the current replay timestamp periodically on the downstream replay control channel * * @param minutesPropagationIntervall says, how often (in minutes) should the timestamp information be sent */ SINT32 startTimeStampPorpagation(UINT32 minutesPropagationIntervall); /** Stops the timestamp propagation*/ SINT32 stopTimeStampPorpagation(); /** Proccesses a getTimeStamps request on a reply control channel * * @param pReceiver the control chanel which receives the getTimeStamps request * @retval E_SUCCESS if the request could be processed successfully * @retval E_UNKNOWN otherwise */ // SINT32 proccessGetTimestamps(const CAReplayControlChannel* pReceiver) const; /** Proccesses a getTimeStamp request on a reply control channel. * * @param pReceiver the control channel which receives the request * @param strMixID the mix id for which the timestamp is requested. If NULL we timestamp of this mix is requested. * @retval E_SUCCESS if the request could be processed successfully * @retval E_UNKNOWN otherwise */ SINT32 proccessGetTimestamp(const CAReplayControlChannel* pReceiver,const UINT8* strMixID) const; /** Proccesses a received replay timestamp rt from mix strMixID * * @param pReceiver the control channel which receives the timestamp * @param strMixID the mix id of the mix which sends the timestamp * @param rt the timestamp * @retval E_SUCCESS if the timestamp was preocessed successfully * @retval E_UNKNOWN otherwise */ SINT32 proccessGotTimestamp(const CAReplayControlChannel* pReceiver,const UINT8* strMixID,const UINT32 offset) const; /** Sends upstram a request for the replay timestamp for the given mix*/ SINT32 sendGetTimestamp(const UINT8* strMixID); private: friend THREAD_RETURN rp_loopPropagateTimestamp(void* param); const CAMixWithReplayDB* m_pMix; CAReplayControlChannel* m_pDownstreamReplayControlChannel; CAReplayControlChannel* m_pUpstreamReplayControlChannel; UINT32 m_u32PropagationInterval; CAThread* m_pThreadTimestampPropagation; //UINT8* m_strGetTimestampsRepsonseMessageTemplate; //UINT32 m_u32GetTimestampsRepsonseMessageTemplateLen; volatile bool m_bRun; XERCES_CPP_NAMESPACE::DOMDocument* m_docTemplate; SINT32 initTimestampsMessageTemplate(); }; #endif anon-proxy-00.05.38+20081230/CAFirstMixChannelList.cpp0000644000175000017500000011162711126465761020537 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #ifndef ONLY_LOCAL_PROXY #include "CAFirstMixChannelList.hpp" #include "CAUtil.hpp" #include "CAMsg.hpp" #include "CAThread.hpp" #define MAX_HASH_KEY 8200 //8113 #ifdef PAYMENT #include "CAAccountingInstance.hpp" #endif const SINT32 CAFirstMixChannelList::EXPIRATION_TIME_SECS = 300; // 5 minutes CAFirstMixChannelList::CAFirstMixChannelList() { m_HashTable=new LP_fmHashTableEntry[MAX_HASH_KEY]; memset(m_HashTable,0,sizeof(LP_fmHashTableEntry)*MAX_HASH_KEY); for(int i=0;isetMainLoop(fml_loopDelayBuckets); m_pThreadDelayBucketsLoop->start(this); #endif } CAFirstMixChannelList::~CAFirstMixChannelList() { #ifdef DELAY_USERS m_bDelayBucketsLoopRun=false; m_pThreadDelayBucketsLoop->join(); delete m_pThreadDelayBucketsLoop; m_pThreadDelayBucketsLoop = NULL; delete m_pMutexDelayChannel; m_pMutexDelayChannel = NULL; delete []m_pDelayBuckets; m_pDelayBuckets = NULL; #endif for(int i=0;igetSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) { FINISH_STACK("CAFirstMixChannelList::add (invalid hash key)"); return NULL; } m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; if(pHashTableEntry->pMuxSocket!=NULL) //the entry in the hashtable for this socket (hashkey) must be empty { FINISH_STACK("CAFirstMixChannelList::add (socket exists)"); m_Mutex.unlock(); return NULL; } //SAVE_STACK("CAFirstMixChannelList::add", "initialising table entry"); pHashTableEntry->pMuxSocket=pMuxSocket; pHashTableEntry->pQueueSend=pQueueSend; pHashTableEntry->pControlMessageQueue = new CAQueue(); pHashTableEntry->pControlChannelDispatcher = new CAControlChannelDispatcher(pHashTableEntry->pControlMessageQueue); pHashTableEntry->uAlreadySendPacketSize=-1; pHashTableEntry->cNumberOfChannels=0; #ifdef LOG_TRAFFIC_PER_USER pHashTableEntry->trafficIn=0; pHashTableEntry->trafficOut=0; getcurrentTimeMillis(pHashTableEntry->timeCreated); #endif #ifdef LOG_DIALOG pHashTableEntry->strDialog=new UINT8[strlen((char*)strDialog)+1]; strcpy((char*)pHashTableEntry->strDialog,(char*)strDialog); #endif getRandom(&(pHashTableEntry->id)); #ifdef PAYMENT pHashTableEntry->pAccountingInfo=NULL; #endif SAVE_STACK("CAFirstMixChannelList::add", "copying peer IP"); memcpy(pHashTableEntry->peerIP,peerIP,4); #ifdef DATA_RETENTION_LOG pHashTableEntry->peerPort=((CASocket*)pMuxSocket)->getPeerPort(); #endif #ifdef DELAY_USERS m_pMutexDelayChannel->lock(); pHashTableEntry->delayBucket=m_u32DelayChannelUnlimitTraffic; //can always send some first packets for(UINT32 i=0;idelayBucketID=i; break; } } m_pDelayBuckets[pHashTableEntry->delayBucketID]=&pHashTableEntry->delayBucket; m_pMutexDelayChannel->unlock(); #endif SAVE_STACK("CAFirstMixChannelList::add", "inserting in connection list"); //now insert the new connection in the list of all open connections if(m_listHashTableHead==NULL) //if first one { pHashTableEntry->list_HashEntries.next=NULL; } else {//add to the head of the double linked list pHashTableEntry->list_HashEntries.next=m_listHashTableHead; m_listHashTableHead->list_HashEntries.prev=pHashTableEntry; } pHashTableEntry->list_HashEntries.prev=NULL; m_listHashTableHead=pHashTableEntry; SAVE_STACK("CAFirstMixChannelList::add", "inserting in timout list"); // insert in timeout list; entries are added to the foot of the list #ifdef PAYMENT pHashTableEntry->bRecoverTimeout = true; /* Hot fix: push timeout entry explicitly to avoid * confusion, when timeout occurs during AI login */ //pushTimeoutEntry_internal(pHashTableEntry); #endif m_Mutex.unlock(); FINISH_STACK("CAFirstMixChannelList::add"); return pHashTableEntry; } ///The maximum number of channels allowed per connection #define MAX_NUMBER_OF_CHANNELS CHANNELS_PER_CLIENT /** Adds a new channel for a given connection to the channel list. * Also a new out-channel id is generated and returned. * @param pMuxSocket the connection from the user * @param channelIn the channel, which should be added * @param pCipher the symmetric cipher associated with this channel * @param channelOut a pointer to the place, there the new generated out-channel id is stored * @retval E_SUCCESS if successful * @retval E_UNKNOWN in case of an error */ SINT32 CAFirstMixChannelList::addChannel(CAMuxSocket* pMuxSocket,HCHANNEL channelIn, CASymCipher* pCipher,HCHANNEL* channelOut) { if(pMuxSocket==NULL||channelOut==NULL) return E_UNKNOWN; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return E_UNKNOWN; m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; if(pHashTableEntry->pMuxSocket==NULL||pHashTableEntry->cNumberOfChannels>=MAX_NUMBER_OF_CHANNELS) { CAMsg::printMsg(LOG_DEBUG,"More than 50 channels!\n"); m_Mutex.unlock(); return E_UNKNOWN; } fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; #ifndef DO_TRACE fmChannelListEntry* pNewEntry=new fmChannelListEntry; #else fmChannelListEntry* pNewEntry=newChannelListEntry(); #endif memset(pNewEntry,0,sizeof(fmChannelListEntry)); pNewEntry->pCipher=pCipher; pNewEntry->channelIn=channelIn; do { getRandom(channelOut); //get new Random OUT-CHANNEL-ID } while(*channelOut<256||get_intern_without_lock(*channelOut)!=NULL); //until it is unused... pNewEntry->channelOut=*channelOut; pNewEntry->bIsSuspended=false; pNewEntry->pHead=pHashTableEntry; #ifdef LOG_CHANNEL pNewEntry->packetsInFromUser=0; pNewEntry->packetsOutToUser=0; #endif #ifdef SSL_HACK pNewEntry->downStreamBytes = 0; #endif //add to the channel list for the given connection if(pEntry==NULL) //First Entry to the channel list { pNewEntry->list_InChannelPerSocket.next=NULL; pNewEntry->list_InChannelPerSocket.prev=NULL; } else { pNewEntry->list_InChannelPerSocket.next=pEntry; pNewEntry->list_InChannelPerSocket.prev=NULL; pEntry->list_InChannelPerSocket.prev=pNewEntry; } pHashTableEntry->pChannelList=pNewEntry; //add to the out-channel list hashkey=(*channelOut)&0x0000FFFF; pEntry=m_HashTableOutChannels[hashkey]; if(pEntry!=NULL) //Hash Table Bucket Over run.... { pNewEntry->list_OutChannelHashTable.prev=NULL; pNewEntry->list_OutChannelHashTable.next=pEntry; pEntry->list_OutChannelHashTable.prev=pNewEntry; } m_HashTableOutChannels[hashkey]=pNewEntry; pHashTableEntry->cNumberOfChannels++; m_Mutex.unlock(); return E_SUCCESS; } /** Returns the general data stored for a given Socket (user) * @param pMuxSocket the connection from the user * @return general data for the given user * @retval NULL if not found */ fmHashTableEntry* CAFirstMixChannelList::get(CAMuxSocket* pMuxSocket) { if(pMuxSocket==NULL) return NULL; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return NULL; m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; m_Mutex.unlock(); return pHashTableEntry; } /** Returns the information for a given Input-Channel-ID * @param pMuxSocket the connection from the user * @param channelIn the channel id * @return all channel associated information (output-channel id, cipher etc.) * @retval NULL if not found */ fmChannelListEntry* CAFirstMixChannelList::get(CAMuxSocket* pMuxSocket,HCHANNEL channelIn) { if(pMuxSocket==NULL) return NULL; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return NULL; m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; while(pEntry!=NULL) { if(pEntry->channelIn==channelIn) { m_Mutex.unlock(); return pEntry; } pEntry=pEntry->list_InChannelPerSocket.next; } m_Mutex.unlock(); return NULL; } #ifdef PAYMENT fmHashTableEntry* CAFirstMixChannelList::popTimeoutEntry() { return popTimeoutEntry(false); } fmHashTableEntry* CAFirstMixChannelList::popTimeoutEntry(bool a_bForce) { fmHashTableEntry* ret; m_Mutex.lock(); ret = popTimeoutEntry_internal(a_bForce); m_Mutex.unlock(); return ret; } fmHashTableEntry* CAFirstMixChannelList::popTimeoutEntry_internal(bool a_bForce) { fmHashTableEntry* pHashTableEntry; if (m_listTimoutHead == NULL) { // there are not entries in the list return NULL; } pHashTableEntry = m_listTimoutHead; if (a_bForce || pHashTableEntry->list_TimeoutHashEntries.timoutSecs <= time(NULL)) { if (removeFromTimeoutList(pHashTableEntry) == E_SUCCESS) { return pHashTableEntry; } else { CAMsg::printMsg(LOG_CRIT, "CAFirstMixChannelList:popTimeoutEntry_internal: Could not remove expired entry from timeout list!\n"); } } return NULL; } #endif #ifdef PAYMENT SINT32 CAFirstMixChannelList::pushTimeoutEntry(fmHashTableEntry* pHashTableEntry) { SINT32 ret; m_Mutex.lock(); ret = pushTimeoutEntry_internal(pHashTableEntry); m_Mutex.unlock(); return ret; } UINT32 CAFirstMixChannelList::countTimeoutEntries() { fmHashTableEntry* pHashTableEntry; UINT32 count = 0; for (pHashTableEntry = m_listTimoutHead; pHashTableEntry != NULL; count++, pHashTableEntry = pHashTableEntry->list_TimeoutHashEntries.next); return count; } #endif #ifdef PAYMENT SINT32 CAFirstMixChannelList::pushTimeoutEntry_internal(fmHashTableEntry* pHashTableEntry) { if (pHashTableEntry == NULL) { return E_UNKNOWN; } INIT_STACK; BEGIN_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal"); //CAMsg::printMsg(LOG_DEBUG,"Entries in timeout list before push: %d\n", countTimeoutEntries()); pHashTableEntry->list_TimeoutHashEntries.timoutSecs = time(NULL) + EXPIRATION_TIME_SECS; //SAVE_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal", "removing from timeout list"); // remove from timeout list if needed before adding it to the end removeFromTimeoutList(pHashTableEntry); if (m_listTimoutFoot == NULL) { //SAVE_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal", "new first entry"); // this is the first entry in the list pHashTableEntry->list_TimeoutHashEntries.prev = NULL; m_listTimoutHead = pHashTableEntry; } else { //SAVE_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal", "new last entry"); // this is the new last entry in the list m_listTimoutFoot->list_TimeoutHashEntries.next = pHashTableEntry; pHashTableEntry->list_TimeoutHashEntries.prev = m_listTimoutFoot; } pHashTableEntry->list_TimeoutHashEntries.next = NULL; m_listTimoutFoot = pHashTableEntry; //CAMsg::printMsg(LOG_DEBUG,"Entries in timeout list after push: %d\n", countTimeoutEntries()); FINISH_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal"); return E_SUCCESS; } #endif #ifdef PAYMENT SINT32 CAFirstMixChannelList::removeFromTimeoutList(fmHashTableEntry* pHashTableEntry) { if (pHashTableEntry == NULL) { return E_UNKNOWN; } if (m_listTimoutHead == NULL || m_listTimoutFoot == NULL) { // there is no entry in the list; therefore this entry does not need to be removed return E_SUCCESS; } if (pHashTableEntry->list_TimeoutHashEntries.prev == NULL && pHashTableEntry->list_TimeoutHashEntries.next == NULL && m_listTimoutHead != pHashTableEntry) { // this entry is not in the list; it does not need to be removed return E_SUCCESS; } if(m_listTimoutHead == pHashTableEntry) //if entry is the head of the connection list { if(m_listTimoutFoot == pHashTableEntry) //if entry is also the last (so the only one in the list..) { //list is now empty m_listTimoutHead = NULL; m_listTimoutFoot = NULL; } else { //remove the head of the list m_listTimoutHead = pHashTableEntry->list_TimeoutHashEntries.next; } } else { //the connection is not the head of the list if(pHashTableEntry->list_TimeoutHashEntries.next == NULL) { //the connection is the last element in the list m_listTimoutFoot = pHashTableEntry->list_TimeoutHashEntries.prev; m_listTimoutFoot->list_TimeoutHashEntries.next = NULL; } else { //it is a simple middle element if (pHashTableEntry->list_TimeoutHashEntries.prev == NULL) { CAMsg::printMsg(LOG_CRIT, "CAFirstMixChannelList:removeFromTimeoutList: No previous element!!\n"); } else { pHashTableEntry->list_TimeoutHashEntries.prev->list_TimeoutHashEntries.next = pHashTableEntry->list_TimeoutHashEntries.next; } if (pHashTableEntry->list_TimeoutHashEntries.next == NULL) { CAMsg::printMsg(LOG_CRIT, "CAFirstMixCahnelList:removeFromTimeoutList: No next element!!\n"); } else { pHashTableEntry->list_TimeoutHashEntries.next->list_TimeoutHashEntries.prev = pHashTableEntry->list_TimeoutHashEntries.prev; } } } pHashTableEntry->list_TimeoutHashEntries.prev = NULL; pHashTableEntry->list_TimeoutHashEntries.next = NULL; return E_SUCCESS; } #endif /** Removes all channels, which belongs to the given connection and * the connection itself from the list. * @param pMuxSocket the connection from the user * @retval E_SUCCESS if successful * @retval E_UNKNOWN in case of an error */ SINT32 CAFirstMixChannelList::remove(CAMuxSocket* pMuxSocket) { if(pMuxSocket==NULL) return E_UNKNOWN; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return E_UNKNOWN; m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; if(pHashTableEntry->pMuxSocket==NULL) //this connection is not in the list { m_Mutex.unlock(); return E_UNKNOWN; } #ifdef DELAY_USERS m_pMutexDelayChannel->lock(); m_pDelayBuckets[pHashTableEntry->delayBucketID]=NULL; m_pMutexDelayChannel->unlock(); #endif pHashTableEntry->pControlChannelDispatcher->deleteAllControlChannels(); delete pHashTableEntry->pControlChannelDispatcher; //deletes the dispatcher and all associated control channels delete pHashTableEntry->pControlMessageQueue; pHashTableEntry->pControlChannelDispatcher = NULL; pHashTableEntry->pControlMessageQueue = NULL; if(m_listHashTableNext==pHashTableEntry) //adjust the enumeration over all connections (@see getNext()) m_listHashTableNext=pHashTableEntry->list_HashEntries.next; if(pHashTableEntry->list_HashEntries.prev==NULL) //if entry is the head of the connection list { if(pHashTableEntry->list_HashEntries.next==NULL) //if entry is also the last (so the only one in the list..) { m_listHashTableHead=NULL; //list is now empty } else {//remove the head of the list m_listHashTableHead=pHashTableEntry->list_HashEntries.next; m_listHashTableHead->list_HashEntries.prev=NULL; } } else { //the connection is not the head of the list if(pHashTableEntry->list_HashEntries.next==NULL) {//the connection is the last element in the list pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=NULL; } else {//its a simple middle element pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=pHashTableEntry->list_HashEntries.next; pHashTableEntry->list_HashEntries.next->list_HashEntries.prev=pHashTableEntry->list_HashEntries.prev; } } #ifdef PAYMENT removeFromTimeoutList(pHashTableEntry); #endif fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; fmChannelListEntry* pTmpEntry; while(pEntry!=NULL)//for all channels.... { //remove the out channel form the out channel hast table hashkey=pEntry->channelOut&0x0000FFFF; pTmpEntry=m_HashTableOutChannels[hashkey]; while(pTmpEntry!=NULL) { if(pTmpEntry->channelOut==pEntry->channelOut) {//we have found the entry if(pTmpEntry->list_OutChannelHashTable.prev==NULL) //it's the head { if(pTmpEntry->list_OutChannelHashTable.next==NULL) {//it's also the last Element m_HashTableOutChannels[hashkey]=NULL; //empty this hash bucket } else { pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; } } else {//not the head if(pTmpEntry->list_OutChannelHashTable.next==NULL) {//but the last pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; } else {//a middle element pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; } } break; } pTmpEntry=pTmpEntry->list_OutChannelHashTable.next; } pTmpEntry=pEntry->list_InChannelPerSocket.next; #ifndef DO_TRACE delete pEntry; pEntry = NULL; #else deleteChannelListEntry(pEntry); #endif pEntry=pTmpEntry; } /* already done by pHashTableEntry->pControlChannelDispatcher->deleteAllControlChannels(); #ifdef PAYMENT // cleanup accounting information CAAccountingInstance::cleanupTableEntry(pHashTableEntry); #endif */ #ifdef LOG_DIALOG delete[] pHashTableEntry->strDialog; pHashTableEntry->strDialog = NULL; #endif memset(pHashTableEntry,0,sizeof(fmHashTableEntry)); //'delete' the connection from the connection hash table m_Mutex.unlock(); return E_SUCCESS; } #ifdef NEW_MIX_TYPE /* some additional methods for TypeB first mixes */ /** * Removes all channels, which belongs to the given connection and * the connection itself from the list but keeps the outgoing channels. * @param pMuxSocket the connection from the user * @retval E_SUCCESS if successful * @retval E_UNKNOWN in case of an error */ SINT32 CAFirstMixChannelList::removeClientPart(CAMuxSocket* pMuxSocket) { if(pMuxSocket==NULL) return E_UNKNOWN; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return E_UNKNOWN; m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; if(pHashTableEntry->pMuxSocket==NULL) //this connection is not in the list { m_Mutex.unlock(); return E_UNKNOWN; } #ifdef DELAY_USERS m_pMutexDelayChannel->lock(); m_pDelayBuckets[pHashTableEntry->delayBucketID]=NULL; m_pMutexDelayChannel->unlock(); #endif pHashTableEntry->pControlChannelDispatcher->deleteAllControlChannels(); delete pHashTableEntry->pControlChannelDispatcher; //deletes the dispatcher and all associated control channels pHashTableEntry->pControlChannelDispatcher = NULL; if(m_listHashTableNext==pHashTableEntry) //adjust the enumeration over all connections (@see getNext()) m_listHashTableNext=pHashTableEntry->list_HashEntries.next; if(pHashTableEntry->list_HashEntries.prev==NULL) //if entry is the head of the connection list { if(pHashTableEntry->list_HashEntries.next==NULL) //if entry is also the last (so the only one in the list..) { m_listHashTableHead=NULL; //list is now empty } else {//remove the head of the list m_listHashTableHead=pHashTableEntry->list_HashEntries.next; m_listHashTableHead->list_HashEntries.prev=NULL; } } else {//the connection is not the head of the list if(pHashTableEntry->list_HashEntries.next==NULL) {//the connection is the last element in the list pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=NULL; } else {//its a simple middle element pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=pHashTableEntry->list_HashEntries.next; pHashTableEntry->list_HashEntries.next->list_HashEntries.prev=pHashTableEntry->list_HashEntries.prev; } } removeFromTimeoutList(pHashTableEntry); fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; while(pEntry!=NULL)//for all channels.... { /* leave a dummy-entry in the out-channels-table until we receive a * CLOSE-message for the channel from the last mix (else we could * re-use it, while the last mix is still using the old channel), * therefore set the the pointer for the in-channel-part to NULL */ pEntry->pHead = NULL; pEntry = pEntry->list_InChannelPerSocket.next; } #ifdef PAYMENT // cleanup accounting information CAAccountingInstance::cleanupTableEntry(pHashTableEntry); #endif memset(pHashTableEntry,0,sizeof(fmHashTableEntry)); //'delete' the connection from the connection hash table m_Mutex.unlock(); return E_SUCCESS; } /** * Removes an out-channel from the table, which is vacant (not connected to * any client). * @param pEntry The vacant out-channel entry. */ void CAFirstMixChannelList::removeVacantOutChannel(fmChannelListEntry* pEntry) { if (pEntry != NULL) { if (pEntry->pHead == NULL) { /* must be a vacant channel */ m_Mutex.lock(); fmChannelListEntry* pTmpEntry; /* check whether the enty is in the out-channel-table */ SINT32 hashkey = pEntry->channelOut & 0x0000FFFF; pTmpEntry = m_HashTableOutChannels[hashkey]; while (pTmpEntry != NULL) { if (pTmpEntry->channelOut == pEntry->channelOut) { //we have found the entry if (pTmpEntry->list_OutChannelHashTable.prev==NULL) { //it's the head if (pTmpEntry->list_OutChannelHashTable.next==NULL) { //it's also the last Element m_HashTableOutChannels[hashkey] = NULL; //empty this hash bucket } else { pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; } } else { //not the head if (pTmpEntry->list_OutChannelHashTable.next==NULL) { //but the last pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; } else { //a middle element pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; } } break; } pTmpEntry=pTmpEntry->list_OutChannelHashTable.next; } /* entry is not in the table any more */ #ifndef DO_TRACE delete pEntry; pEntry = NULL; #else deleteChannelListEntry(pEntry); #endif m_Mutex.unlock(); } } } /** * Removes all out-channels from the table, which are vacant (not connected to * any client). Also the channel-cipher is deleted. */ void CAFirstMixChannelList::cleanVacantOutChannels() { m_Mutex.lock(); SINT32 hashkey = 0; do { fmChannelListEntry* pTmpEntry = m_HashTableOutChannels[hashkey]; while (pTmpEntry != NULL) { if (pTmpEntry->pHead == NULL) { /* we have found a vacant channel */ if (pTmpEntry->list_OutChannelHashTable.prev==NULL) { //it's the head if (pTmpEntry->list_OutChannelHashTable.next==NULL) { //it's also the last Element m_HashTableOutChannels[hashkey] = NULL; //empty this hash bucket } else { pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; } } else { //not the head if (pTmpEntry->list_OutChannelHashTable.next==NULL) { //but the last pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; } else { //a middle element pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; } } /* entry is removed from the table, now delete the channel-cipher */ delete pTmpEntry->pCipher; pTmpEntry->pCipher = NULL; fmChannelListEntry* pRemoveEntry = pTmpEntry; pTmpEntry = pTmpEntry->list_OutChannelHashTable.next; /* delete the entry */ #ifndef DO_TRACE delete pRemoveEntry; pRemoveEntry = NULL; #else deleteChannelListEntry(pEntry); #endif } else { /* not a vacant channel -> try the next channel in the hashtable-line */ pTmpEntry = pTmpEntry->list_OutChannelHashTable.next; } } /* we have processed a whole line of the channel-table -> process the next * one */ hashkey = (hashkey + 1) & 0x0000FFFF; } while (hashkey != 0); /* we have processed the whole out-channel-table */ m_Mutex.unlock(); } #endif //NEW_MIX_TYPE (TypeB first mixes) /** Removes a single channel from the list. * @param pMuxSocket the connection from the user * @param channelIn the channel, which should be removed * @retval E_SUCCESS if successful * @retval E_UNKNOWN in case of an error */ SINT32 CAFirstMixChannelList::removeChannel(CAMuxSocket* pMuxSocket,HCHANNEL channelIn) { if(pMuxSocket==NULL) return E_UNKNOWN; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return E_UNKNOWN; m_Mutex.lock(); fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; if(pHashTableEntry->pMuxSocket==NULL) { m_Mutex.unlock(); return E_UNKNOWN; } fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; while(pEntry!=NULL) { if(pEntry->channelIn==channelIn) //search for the channel { hashkey=pEntry->channelOut&0x0000FFFF; //remove the out channel from the out channel hash table fmChannelListEntry*pTmpEntry=m_HashTableOutChannels[hashkey]; while(pTmpEntry!=NULL) { if(pTmpEntry->channelOut==pEntry->channelOut) {//found it in the out channel hash table if(pTmpEntry->list_OutChannelHashTable.prev==NULL) //head { if(pTmpEntry->list_OutChannelHashTable.next==NULL) { m_HashTableOutChannels[hashkey]=NULL; } else { pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; } } else { if(pTmpEntry->list_OutChannelHashTable.next==NULL) {//last element pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; } else {//middle element pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; } } break; } pTmpEntry=pTmpEntry->list_OutChannelHashTable.next; } //remove the channel from the channel hast table if(pEntry->list_InChannelPerSocket.prev==NULL) //head { if(pEntry->list_InChannelPerSocket.next==NULL) {//the only element pHashTableEntry->pChannelList=NULL; } else { pEntry->list_InChannelPerSocket.next->list_InChannelPerSocket.prev=NULL; pHashTableEntry->pChannelList=pEntry->list_InChannelPerSocket.next; } } else { if(pEntry->list_InChannelPerSocket.next==NULL) {//the last element pEntry->list_InChannelPerSocket.prev->list_InChannelPerSocket.next=NULL; } else {//a middle element pEntry->list_InChannelPerSocket.prev->list_InChannelPerSocket.next=pEntry->list_InChannelPerSocket.next; pEntry->list_InChannelPerSocket.next->list_InChannelPerSocket.prev=pEntry->list_InChannelPerSocket.prev; } } #ifndef DO_TRACE delete pEntry; pEntry = NULL; #else deleteChannelListEntry(pEntry); #endif pHashTableEntry->cNumberOfChannels--; m_Mutex.unlock(); return E_SUCCESS; } pEntry=pEntry->list_InChannelPerSocket.next; //try next channel } m_Mutex.unlock(); return E_UNKNOWN;//not found } /** Gets the first connection of all connections in the list. * @see getNext() * @return first connection in the list * @retval NULL if no connection is in the list */ fmHashTableEntry* CAFirstMixChannelList::getFirst() { m_Mutex.lock(); if(m_listHashTableHead!=NULL) m_listHashTableNext=m_listHashTableHead->list_HashEntries.next; else m_listHashTableNext=NULL; m_Mutex.unlock(); return m_listHashTableHead; } /** Gets the next entry in the connections-list. * @see getFirst() * @return next entry in the connection list * @retval NULL in case of an error */ fmHashTableEntry* CAFirstMixChannelList::getNext() { m_Mutex.lock(); fmHashTableEntry* tmpEntry=m_listHashTableNext; if(m_listHashTableNext!=NULL) m_listHashTableNext=m_listHashTableNext->list_HashEntries.next; m_Mutex.unlock(); return tmpEntry; } /** Gets the first channel for a given connection. * @see getNextChannel() * @param pMuxSocket the connection from the user * @return the channel and the associated information * @retval NULL if no channel for this connection exists at the moment */ fmChannelListEntry* CAFirstMixChannelList::getFirstChannelForSocket(CAMuxSocket* pMuxSocket) { if(pMuxSocket==NULL) return NULL; SINT32 hashkey=pMuxSocket->getSocket(); if(hashkey>MAX_HASH_KEY-1||hashkey<0) return NULL; fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; return pHashTableEntry->pChannelList; } /** Gets the next channel for a given connection. * @see getFirstChannelForSocket() * @param pEntry a entry returned by a previos call to getFirstChannelForSocket() or getNextChannel() * @return the next channel and all associated information * @retval NULL if there are no more channels for this connection */ fmChannelListEntry* CAFirstMixChannelList::getNextChannel(fmChannelListEntry* pEntry) { if(pEntry==NULL) return NULL; return pEntry->list_InChannelPerSocket.next; } SINT32 CAFirstMixChannelList::test() { CAFirstMixChannelList* pList=new CAFirstMixChannelList(); CAMuxSocket *pMuxSocket=new CAMuxSocket(); ((CASocket*)pMuxSocket)->create(); UINT8 peerIP[4]; #ifndef LOG_DIALOG pList->add(pMuxSocket,peerIP,NULL); #else pList->add(pMuxSocket,peerIP,NULL,(UINT8*)"1"); #endif #if defined(HAVE_CRTDBG) _CrtMemState s1, s2, s3; _CrtMemCheckpoint( &s1 ); #endif UINT32 /*channelIn,*/i,channelOut; for(i=0;i<50;i++) pList->addChannel(pMuxSocket,i,NULL,&channelOut); for(i=0;i<50;i++) pList->removeChannel(pMuxSocket,i); #if defined(HAVE_CRTDBG) _CrtMemCheckpoint( &s2 ); if ( _CrtMemDifference( &s3, &s1, &s2 ) ) _CrtMemDumpStatistics( &s3 ); #endif pList->remove(pMuxSocket); delete pMuxSocket; pMuxSocket = NULL; delete pList; pList = NULL; return E_SUCCESS; } #ifdef DELAY_USERS THREAD_RETURN fml_loopDelayBuckets(void* param) { INIT_STACK; BEGIN_STACK("CAFirstMixChannelList::fml_loopDelayBuckets"); CAFirstMixChannelList* pChannelList=(CAFirstMixChannelList*)param; volatile UINT32** pDelayBuckets=pChannelList->m_pDelayBuckets; while(pChannelList->m_bDelayBucketsLoopRun) { pChannelList->m_pMutexDelayChannel->lock(); UINT32 u32BucketGrow=pChannelList->m_u32DelayChannelBucketGrow; UINT32 u32MaxBucket=u32BucketGrow*10; for(UINT32 i=0;im_pMutexDelayChannel->unlock(); msSleep(pChannelList->m_u32DelayChannelBucketGrowIntervall); } FINISH_STACK("CAFirstMixChannelList::fml_loopDelayBuckets"); THREAD_RETURN_SUCCESS; } void CAFirstMixChannelList::decDelayBuckets(UINT32 delayBucketID) { m_pMutexDelayChannel->lock(); if(delayBucketID < MAX_POLLFD) { if(m_pDelayBuckets[delayBucketID] != NULL) { *(m_pDelayBuckets[delayBucketID]) -= ( (*(m_pDelayBuckets[delayBucketID])) > 0 ) ? 1 : 0; } /*CAMsg::printMsg(LOG_DEBUG,"DelayBuckets decrementing ID %u downto %u\n", delayBucketID, (*(m_pDelayBuckets[delayBucketID])) );*/ } m_pMutexDelayChannel->unlock(); } bool CAFirstMixChannelList::hasDelayBuckets(UINT32 delayBucketID) { bool ret = false; m_pMutexDelayChannel->lock(); if(delayBucketID < MAX_POLLFD) { if(m_pDelayBuckets[delayBucketID] != NULL) { ret = ( (*(m_pDelayBuckets[delayBucketID])) > 0 ); } } m_pMutexDelayChannel->unlock(); return ret; } void CAFirstMixChannelList::setDelayParameters(UINT32 unlimitTraffic,UINT32 bucketGrow,UINT32 intervall) { m_pMutexDelayChannel->lock(); CAMsg::printMsg(LOG_DEBUG,"CAFirstMixChannelList - Set new traffic limit per user- unlimit: %u bucketgrow: %u intervall %u\n", unlimitTraffic,bucketGrow,intervall); m_u32DelayChannelUnlimitTraffic=unlimitTraffic; m_u32DelayChannelBucketGrow=bucketGrow; m_u32DelayChannelBucketGrowIntervall=intervall; for(UINT32 i=0;iunlock(); } #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/CAAccountingBIInterface.cpp0000644000175000017500000002337011116234502020752 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #ifdef PAYMENT #include "CAAccountingBIInterface.hpp" #include "CACmdLnOptions.hpp" #include "CAMsg.hpp" #include "CASocketAddrINet.hpp" #include "CASocket.hpp" #include "CAHttpClient.hpp" //extern CACmdLnOptions* pglobalOptions; //CAMutex* CAAccountingBIInterface::m_pPiInterfaceMutex = new CAMutex(); //CAAccountingBIInterface *CAAccountingBIInterface::m_pPiInterfaceSingleton = NULL; /** * private constructor * just initializes fields, server configuration is done separately */ CAAccountingBIInterface::CAAccountingBIInterface() { //m_pSocket =NULL; //m_pPiInterfaceMutex = new CAMutex(); m_pSocket = new CATLSClientSocket(); m_pPiServerAddress = new CASocketAddrINet(); m_phttpClient = new CAHttpClient(); } /** * private destructor */ CAAccountingBIInterface::~CAAccountingBIInterface() { terminateBIConnection(); if(m_pSocket!=NULL) { delete m_pSocket; m_pSocket = NULL; } if(m_pPiServerAddress!=NULL) { delete m_pPiServerAddress; m_pPiServerAddress = NULL; } if(m_phttpClient!=NULL) { delete m_phttpClient; m_phttpClient = NULL; } /*if(m_pPiInterfaceMutex!=NULL) { delete m_pPiInterfaceMutex; m_pPiInterfaceMutex = NULL; }*/ } SINT32 CAAccountingBIInterface::setPIServerConfiguration(CAXMLBI* pPiServerConfig) { UINT8 *pPiName = NULL; UINT16 piPort = 0; CACertificate *pPiCert = NULL; //m_pPiInterfaceMutex->lock(); if(pPiServerConfig==NULL) { CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: could not configure PI interface: no proper configuration given.\n"); //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } pPiName = pPiServerConfig->getHostName(); pPiCert = pPiServerConfig->getCertificate(); piPort = (UINT16)pPiServerConfig->getPortNumber(); if(pPiName==NULL) { CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: could not configure PI interface: no PI name specified.\n"); //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } if(pPiCert==NULL) { CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: could not configure PI interface: no PI certificate specified.\n"); //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } if(m_pPiServerAddress == NULL) { //Should never happen #ifdef DEBUG CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no server address initialized while trying to configure PI interface.\n"); #endif m_pPiServerAddress = new CASocketAddrINet(); } m_pPiServerAddress->setAddr(pPiName, piPort); m_pPiServerCertificate = pPiCert; //m_pPiInterfaceMutex->unlock(); return E_SUCCESS; } /** * Establishes HTTP(s) connection to the BI (JPI) */ SINT32 CAAccountingBIInterface::initBIConnection() { SINT32 rc; UINT8 buf[64]; memset(buf,0,64); //m_pPiInterfaceMutex->lock(); if(m_pPiServerAddress == NULL) { //Should never happen #ifdef DEBUG CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: no address initialized while trying to connect. Connect aborted.\n"); #endif //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } if(m_pSocket == NULL) { //Should never happen #ifdef DEBUG CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no socket initialized while trying to connect. Creating new one.\n"); #endif m_pSocket = new CATLSClientSocket(); } if(m_pPiServerCertificate == NULL) { CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no PI server certificate specified. Connect aborted.\n"); //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } // connect m_pSocket->setServerCertificate(m_pPiServerCertificate); rc=m_pSocket->connect(*m_pPiServerAddress, PI_CONNECT_TIMEOUT); if(rc!=E_SUCCESS) { m_pPiServerAddress->getHostName(buf, 64); CAMsg::printMsg( LOG_ERR, "CAAccountingBIInterface: Could not connect to BI at %s:%i. Reason: %i\n", buf, m_pPiServerAddress->getPort(), rc //pBI->getHostName(), pBI->getPortNumber(), rc ); m_pSocket->close(); //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } m_pPiServerAddress->getHostName(buf, 64); CAMsg::printMsg(LOG_DEBUG,"CAAccountingBIInterface: BI connection to %s:%i established!\n", buf,m_pPiServerAddress->getPort()); m_phttpClient->setSocket(m_pSocket); //m_pPiInterfaceMutex->unlock(); return E_SUCCESS; } /** * Terminate HTTP(s) connection to the BI (JPI) */ SINT32 CAAccountingBIInterface::terminateBIConnection() { //m_pPiInterfaceMutex->lock(); if(m_pSocket == NULL) { //Should never happen #ifdef DEBUG CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no socket initialized while trying to close connection.\n"); #endif //m_pPiInterfaceMutex->unlock(); return E_UNKNOWN; } m_pSocket->close(); //m_pPiInterfaceMutex->unlock(); return E_SUCCESS; } /** * Send a cost confirmation to the JPI * TODO: Error handling */ CAXMLErrorMessage * CAAccountingBIInterface::settle(CAXMLCostConfirmation &cc) { UINT8 * pStrCC=NULL; UINT8* response=NULL; UINT32 contentLen=0, status=0; UINT32 ret = 0; CAXMLErrorMessage *pErrMsg; //m_pPiInterfaceMutex->lock(); pStrCC = cc.dumpToMem(&contentLen); if( pStrCC==NULL || m_phttpClient->sendPostRequest((UINT8*)"/settle", pStrCC,contentLen)!= E_SUCCESS) { delete[] pStrCC; pStrCC = NULL; //m_pPiInterfaceMutex->unlock(); return NULL; } delete[] pStrCC; pStrCC = NULL; contentLen=0; status=0; m_pSocket->setNonBlocking(true); ret = m_phttpClient->parseHTTPHeader(&contentLen, &status, 3000); if( ret !=E_SUCCESS || (status!=200) || (contentLen==0)) { if(ret == E_TIMEDOUT) { CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: timeout while receiving response!\n"); } else { CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: received bad response from PI!\n"); } //m_pPiInterfaceMutex->unlock(); return NULL; } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: got response header [Status,content-Lenght]=[%i,%i]!\n",status,contentLen); #endif response = new UINT8[contentLen+1]; ret = m_pSocket->receiveFullyT(response, contentLen, 3000); if(ret !=E_SUCCESS) { if(ret == E_TIMEDOUT) { CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: timeout while receiving settle message!\n"); } else { CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: error\n"); } delete[] response; response = NULL; //m_pPiInterfaceMutex->unlock(); return NULL; } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: response body received!\n"); #endif response[contentLen]='\0'; pErrMsg = new CAXMLErrorMessage(response); delete[] response; response = NULL; //m_pPiInterfaceMutex->unlock(); return pErrMsg; } /*CAAccountingBIInterface *CAAccountingBIInterface::getInstance(CAXMLBI* pPiServerConfig) { SINT32 ret; m_pPiInterfaceMutex->lock(); if(m_pPiInterfaceSingleton == NULL) { if(pPiServerConfig == NULL) { CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::could not create PI interface: no proper configuration specified!\n"); m_pPiInterfaceMutex->unlock(); return NULL; } m_pPiInterfaceSingleton = new CAAccountingBIInterface(); ret = m_pPiInterfaceSingleton->setPIServerConfiguration(pPiServerConfig); if(ret != E_SUCCESS) { CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::could not create PI interface: no proper configuration specified!\n"); m_pPiInterfaceMutex->unlock(); return NULL; } } else { CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface:: PI Interface already running!\n"); } m_pPiInterfaceMutex->unlock(); return m_pPiInterfaceSingleton; }*/ /* ** * Request a new Balance certificate from the JPI * TODO: Error handling * * @param balanceCert an old balance certificate that the AI wishes to update * @param response a buffer to receive the new balanceCert * @param responseLen the maximum size of the buffer * SINT32 CAAccountingBIInterface::update(UINT8 *balanceCert, UINT8 * response, UINT32 *responseLen) { UINT8 requestF[] = "\n\n%s\n"; UINT32 sendbuflen = strlen((char *)balanceCert) + strlen((char *)requestF) + 10; UINT8* sendbuf=new UINT8[sendbuflen]; UINT32 status; sprintf((char *)sendbuf, (char *)requestF, (char *)balanceCert); m_httpClient.sendPostRequest((UINT8 *)"/update", sendbuf, strlen((char *)sendbuf)); delete sendbuf; receiveResponse(&status, response, responseLen); return E_SUCCESS; } */ #endif anon-proxy-00.05.38+20081230/CADynamicCascadeConfigurator.hpp0000644000175000017500000000252010526352253022046 0ustar daviddavid#ifndef __CADYNAMICCASCADECONFIGURATOR__ #define __CADYNAMICCASCADECONFIGURATOR__ #include "StdAfx.h" #ifdef DYNAMIC_MIX #include "xml/DOM_Output.hpp" #include "CASocketAddrINet.hpp" #include "CAInfoServiceAware.hpp" #include "CAInfoService.hpp" struct _proposer_t { struct _proposer_t* next; UINT8* ski; }; typedef struct _proposer_t PROPOSERENTRY; typedef struct _proposer_t PROPOSERLIST; struct _proposal_t { struct _proposal_t* next; PROPOSERLIST* proposers; UINT8* proposal; UINT32 count; DOM_Node elem; }; typedef struct _proposal_t PROPOSALENTRY; typedef struct _proposal_t PROPOSALLIST; #define MIN_MAJORITY_QUOTE(x) (UINT32)((2*x)/3)+1 #define MAX_CONTENT_LENGTH 0x00FFFF class CADynamicCascadeConfigurator : CAInfoServiceAware { public: CADynamicCascadeConfigurator(CASignature *a_pSignature, CAMix *a_pMix); ~CADynamicCascadeConfigurator(); SINT32 configure(); private: PROPOSALLIST* m_proposals; SINT32 getMajorityVote(UINT32 a_nrInfoServices, DOM_Node *&r_majorityElem, UINT8* r_strProposal); SINT32 addProposal(DOM_Element a_elem); PROPOSALENTRY *createProposal(UINT8* a_strProposal, UINT32 a_lenProposal, UINT8 *a_strProposer, UINT32 a_lenProposer, DOM_Element *a_elem); SINT32 reconfigureMix(DOM_Node a_elemNewCascade, UINT8* a_strProposal); CASignature *m_pSignature; CAMix *m_pMix; }; #endif //DYNAMIC_MIX #endif anon-proxy-00.05.38+20081230/CALastMixChannelList.hpp0000644000175000017500000001326411047060556020351 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CALASTMIXCHANNELLIST__ #define __CALASTMIXCHANNELLIST__ #ifndef ONLY_LOCAL_PROXY #include "CASocket.hpp" #include "CAMuxSocket.hpp" #include "CAQueue.hpp" #include "CASymCipher.hpp" #include "CAMutex.hpp" #include "CAMsg.hpp" #include "CAThread.hpp" #define HASHTABLE_SIZE 0x00010000 #define HASH_MASK 0x0000FFFF struct t_lastmixchannellist { public: HCHANNEL channelIn; CASymCipher* pCipher; CASocket* pSocket; CAQueue* pQueueSend; #ifdef DELAY_CHANNELS UINT32 delayBucket; UINT32 delayBucketID; #endif #if defined (LOG_CHANNEL) UINT64 timeCreated; #endif #if defined (DELAY_CHANNELS_LATENCY) UINT64 timeLatency; #endif #ifdef LOG_CHANNEL UINT32 trafficInFromUser; UINT32 packetsDataOutToUser; UINT32 packetsDataInFromUser; UINT32 trafficOutToUser; #endif #ifdef NEW_FLOW_CONTROL SINT32 sendmeCounter; //this counts how many packets are sent to the user without an ack recevied yet. #endif private: struct { struct t_lastmixchannellist* prev; struct t_lastmixchannellist* next; } list_Channels; struct { struct t_lastmixchannellist* prev; struct t_lastmixchannellist* next; } list_Sockets; friend class CALastMixChannelList; }; typedef struct t_lastmixchannellist lmChannelList; typedef struct t_lastmixchannellist lmChannelListEntry; typedef lmChannelListEntry* LP_lmChannelListEntry; #ifdef DELAY_CHANNELS THREAD_RETURN lml_loopDelayBuckets(void*); #endif class CALastMixChannelList { public: CALastMixChannelList(); ~CALastMixChannelList(); SINT32 add(HCHANNEL id,CASocket* pSocket,CASymCipher* pCipher,CAQueue* pQueue #ifdef LOG_CHANNEL ,UINT64 timecreated,UINT32 trafficIn #endif #if defined(DELAY_CHANNELS_LATENCY) ,UINT64 delaytime #endif ); lmChannelListEntry* get(HCHANNEL channelIn) { lmChannelListEntry* akt=m_HashTable[channelIn & HASH_MASK]; while(akt!=NULL) { if(akt->channelIn==channelIn) return akt; akt=akt->list_Channels.next; } return NULL; } lmChannelListEntry* getFirstSocket() { if(m_listSockets!=NULL) m_listSocketsNext=m_listSockets->list_Sockets.next; else m_listSocketsNext=NULL; return m_listSockets; } lmChannelListEntry* getNextSocket() { lmChannelListEntry* akt=m_listSocketsNext; if(m_listSocketsNext!=NULL) m_listSocketsNext=m_listSocketsNext->list_Sockets.next; return akt; } // SINT32 removeChannel(CASocket* pSocket); SINT32 removeChannel(HCHANNEL channelIn); UINT32 getSize(){return m_nChannels;} static SINT32 test(); private: UINT32 m_nChannels; //Number of channels in list ///The Hash-Table of all channels. LP_lmChannelListEntry* m_HashTable; ///Pointer to the head of a list of all sockets. lmChannelList* m_listSockets; ///Next Element in the enumeration of all sockets. lmChannelList* m_listSocketsNext; ///This mutex is used in all functions and makes them thread safe. CAMutex m_Mutex; #ifdef DELAY_CHANNELS UINT32** m_pDelayBuckets; CAThread* m_pThreadDelayBucketsLoop; CAMutex* m_pMutexDelayChannel; bool m_bDelayBucketsLoopRun; friend THREAD_RETURN lml_loopDelayBuckets(void*); //Parameters volatile UINT32 m_u32DelayChannelUnlimitTraffic; //how much traffic without any delay? volatile UINT32 m_u32DelayChannelBucketGrow; //how many bytes to put in each bucket per time intervall volatile UINT32 m_u32DelayChannelBucketGrowIntervall; //duration of one time intervall in ms //therefore the allowed bandwith=BucketGrow/Intervall*1000 [bytes/s] public: void setDelayParameters(UINT32 unlimitTraffic,UINT32 bucketGrow,UINT32 intervall); void reduceDelayBuckets(UINT32 delayBucketID, UINT32 amount); bool hasDelayBuckets(UINT32 delayBucketID); UINT32 getDelayBuckets(UINT32 delayBucketID); #endif #ifdef DELAY_CHANNELS_LATENCY //Parameters volatile UINT32 m_u32DelayChannelLatency; //min latency in ms public: void setDelayLatencyParameters(UINT32 latency); #endif }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/CADataRetentionLog.hpp0000644000175000017500000000036011125170632020031 0ustar daviddavid#include "CADataRetentionLogFile.hpp" class CADataRetentionLog { public: CADataRetentionLog(); SINT32 setLogDir(UINT8* strLogDir); SINT32 log(t_dataretentionLogEntry*); private: CADataRetentionLogFile* m_pLogFile; };anon-proxy-00.05.38+20081230/CAAccountingInstance.cpp0000644000175000017500000027515211123430142020406 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #ifdef PAYMENT #include "CAAccountingInstance.hpp" #include "CAAccountingControlChannel.hpp" #include "CABase64.hpp" #include "CAMsg.hpp" #include "CAUtil.hpp" #include "CASignature.hpp" #include "CAThreadPool.hpp" #include "CAXMLErrorMessage.hpp" #include "Hashtable.hpp" #include "packetintro.h" //for testing purposes only #define JAP_DIGEST_LENGTH 28 extern CACmdLnOptions* pglobalOptions; XERCES_CPP_NAMESPACE::DOMDocument* CAAccountingInstance::m_preparedCCRequest; const SINT32 CAAccountingInstance::HANDLE_PACKET_CONNECTION_OK = 1; const SINT32 CAAccountingInstance::HANDLE_PACKET_CONNECTION_UNCHECKED = 4; const SINT32 CAAccountingInstance::HANDLE_PACKET_HOLD_CONNECTION = 0; const SINT32 CAAccountingInstance::HANDLE_PACKET_PREPARE_FOR_CLOSING_CONNECTION = 2; const SINT32 CAAccountingInstance::HANDLE_PACKET_CLOSE_CONNECTION = 3; SINT32 CAAccountingInstance::m_prepaidBytesMinimum = 0; /** * Singleton: This is the reference to the only instance of this class */ CAAccountingInstance * CAAccountingInstance::ms_pInstance = NULL; const UINT64 CAAccountingInstance::PACKETS_BEFORE_NEXT_CHECK = 100; const UINT32 CAAccountingInstance::MAX_TOLERATED_MULTIPLE_LOGINS = 10; /** * private Constructor */ CAAccountingInstance::CAAccountingInstance(CAMix* callingMix) { CAMsg::printMsg( LOG_DEBUG, "AccountingInstance initialising\n" ); m_seqBIConnErrors = 0; m_pMutex = new CAMutex(); //m_pIPBlockList = new CATempIPBlockList(60000); m_pSettlementMutex = new CAConditionVariable(); //m_loginHashTableChangeInProgress = false; //for synchronizing settlementTransactions of loginThreads and SettlementThread. m_nextSettleNr = 0; //The next thread's number to alter the login hash table m_settleWaitNr = 0; //The wait number when it is equal to nextSettle number it's the thread's turn has to to //alter the login hash table // initialize Database connection //m_dbInterface = new CAAccountingDBInterface(); m_pPiInterface = new CAAccountingBIInterface(); /*if(m_dbInterface->initDBConnection() != E_SUCCESS) { CAMsg::printMsg( LOG_ERR, "**************** AccountingInstance: Could not connect to DB!\n"); exit(1); }*/ // initialize JPI signature tester m_AiName = new UINT8[256]; pglobalOptions->getAiID(m_AiName, 256); if (pglobalOptions->getBI() != NULL) { m_pJpiVerifyingInstance = pglobalOptions->getBI()->getVerifier(); m_pPiInterface->setPIServerConfiguration(pglobalOptions->getBI()); } m_iHardLimitBytes = pglobalOptions->getPaymentHardLimit(); m_iSoftLimitBytes = pglobalOptions->getPaymentSoftLimit(); prepareCCRequest(callingMix, m_AiName); m_currentAccountsHashtable = new Hashtable((UINT32 (*)(void *))Hashtable::hashUINT64, (SINT32 (*)(void *,void *))Hashtable::compareUINT64, 2000); m_certHashCC = new Hashtable((UINT32 (*)(void *))Hashtable::stringHash, (SINT32 (*)(void *,void *))Hashtable::stringCompare); for (UINT32 i = 0; i < m_allHashesLen; i++) { m_certHashCC->put(m_allHashes[i], m_allHashes[i]); } // launch BI settleThread m_pSettleThread = new CAAccountingSettleThread(m_currentAccountsHashtable, m_currentCascade); m_aiThreadPool = new CAThreadPool(NUM_LOGIN_WORKER_TRHEADS, MAX_LOGIN_QUEUE, false); } /** * private destructor */ CAAccountingInstance::~CAAccountingInstance() { INIT_STACK; BEGIN_STACK("~CAAccountingInstance"); /* * avoid calling this desctructor concurrently! */ m_pMutex->lock(); CAMsg::printMsg( LOG_DEBUG, "AccountingInstance dying\n" ); if (m_pSettleThread) { CAMsg::printMsg( LOG_DEBUG, "deleting m_pSettleThread\n" ); //m_pSettleThread->settle(); delete m_pSettleThread; m_pSettleThread = NULL; } if (m_aiThreadPool) { CAMsg::printMsg( LOG_DEBUG, "deleting m_aiThreadPool\n" ); delete m_aiThreadPool; m_aiThreadPool = NULL; } /*if (m_dbInterface) { CAMsg::printMsg( LOG_DEBUG, "termintaing dbConnection\n" ); m_dbInterface->terminateDBConnection(); delete m_dbInterface; } m_dbInterface = NULL;*/ delete m_pPiInterface; m_pPiInterface = NULL; delete m_pSettlementMutex; m_pSettlementMutex = NULL; //delete m_pIPBlockList; //m_pIPBlockList = NULL; delete[] m_AiName; m_AiName = NULL; if (m_currentAccountsHashtable) { m_currentAccountsHashtable->getMutex()->lock(); CAMsg::printMsg( LOG_DEBUG, "CAAccountingInstance: Clearing accounts hashtable...\n"); m_currentAccountsHashtable->clear(HASH_EMPTY_NONE, HASH_EMPTY_DELETE); CAMsg::printMsg( LOG_DEBUG, "CAAccountingInstance: Deleting accounts hashtable...\n" ); m_currentAccountsHashtable->getMutex()->unlock(); delete m_currentAccountsHashtable; m_currentAccountsHashtable = NULL; } m_currentAccountsHashtable = NULL; CAMsg::printMsg( LOG_DEBUG, "CAAccountingInstance: Accounts hashtable deleted.\n" ); delete[] m_currentCascade; m_currentCascade = NULL; if(m_certHashCC != NULL) { for (UINT32 i = 0; i < m_allHashesLen; i++) { UINT8* certHash = (UINT8*)m_certHashCC->remove(m_allHashes[i]); } m_certHashCC->clear(HASH_EMPTY_NONE, HASH_EMPTY_DELETE); delete m_certHashCC; m_certHashCC = NULL; } if (m_allHashes) { for (UINT32 i = 0; i < m_allHashesLen; i++) { delete m_allHashes[i]; m_allHashes[i] = NULL; } delete[] m_allHashes; } m_allHashes = NULL; m_pMutex->unlock(); delete m_pMutex; m_pMutex = NULL; FINISH_STACK("~CAAccountingInstance"); CAMsg::printMsg( LOG_DEBUG, "AccountingInstance dying finished.\n" ); } UINT32 CAAccountingInstance::getAuthFlags(fmHashTableEntry * pHashEntry) { if (pHashEntry == NULL) { return 0; } tAiAccountingInfo* pAccInfo = pHashEntry->pAccountingInfo; if (pAccInfo == NULL) { return 0; } return pAccInfo->authFlags; } UINT32 CAAccountingInstance::getNrOfUsers() { UINT32 users = 0; if (ms_pInstance != NULL) { ms_pInstance->m_pMutex->lock(); if(ms_pInstance->m_currentAccountsHashtable != NULL) { // getting the size is an atomic operation and does not need synchronization users = ms_pInstance->m_currentAccountsHashtable->getSize(); } else { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: Trying to access Hashtable after it has been disposed!!.\n"); } ms_pInstance->m_pMutex->unlock(); } return users; } THREAD_RETURN CAAccountingInstance::processThread(void* a_param) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::processThread"); aiQueueItem* item = (aiQueueItem*)a_param; bool bDelete = false; DOMElement *elem = item->pDomDoc->getDocumentElement(); // call the handle function (ms_pInstance->*(item->handleFunc))(item->pAccInfo, elem); item->pAccInfo->mutex->lock(); item->pAccInfo->nrInQueue--; if (item->pAccInfo->authFlags & AUTH_DELETE_ENTRY && item->pAccInfo->nrInQueue == 0) { /* * There is no more entry of this connection in the queue, * and the connection is closed. We have to delete the entry. */ bDelete = true; CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Deleting account entry from AI thread.\n"); } if (item->pAccInfo->nrInQueue < 0) { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: AI thread found negative handle queue!\n"); } item->pAccInfo->mutex->unlock(); if (bDelete) { delete item->pAccInfo->mutex; item->pAccInfo->mutex = NULL; delete item->pAccInfo; item->pAccInfo = NULL; } delete item->pDomDoc; item->pDomDoc = NULL; delete item; item = NULL; FINISH_STACK("CAAccountingInstance::processThread"); THREAD_RETURN_SUCCESS; } SINT32 CAAccountingInstance::handleJapPacket(fmHashTableEntry *pHashEntry, bool a_bControlMessage, bool a_bMessageToJAP) { SINT32 ret = handleJapPacket_internal(pHashEntry, a_bControlMessage, a_bMessageToJAP); INIT_STACK; FINISH_STACK("CAAccountingInstance::handleJapPacket"); return ret; } /** * Called by FirstMix for each incoming JAP packet. * Determines whether the packet should be let through or not * * Possible return values, and FirstMix's reaction: * @return 1: everything is OK, forward packet to next mix * @return 2: we need something (cert, CC,...) from the user, hold packet and start timeout * @return 3: fatal error, or timeout exceeded -> kick the user out * */ SINT32 CAAccountingInstance::handleJapPacket_internal(fmHashTableEntry *pHashEntry, bool a_bControlMessage, bool a_bMessageToJAP) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::handleJapPacket"); CAAccountingDBInterface *dbInterface = NULL; if (pHashEntry == NULL || pHashEntry->pAccountingInfo == NULL) { return HANDLE_PACKET_CLOSE_CONNECTION; } tAiAccountingInfo* pAccInfo = pHashEntry->pAccountingInfo; AccountLoginHashEntry* loginEntry = NULL; CAXMLErrorMessage* err = NULL; pAccInfo->mutex->lock(); if (pAccInfo->authFlags & AUTH_DELETE_ENTRY) { pAccInfo->mutex->unlock(); return HANDLE_PACKET_CLOSE_CONNECTION; } if ( (pAccInfo->authFlags & AUTH_LOGIN_NOT_FINISHED) && !a_bMessageToJAP ) { CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: User violates login protocol"); pAccInfo->mutex->unlock(); return HANDLE_PACKET_CLOSE_CONNECTION; } //kick user out after previous error if(pAccInfo->authFlags & AUTH_FATAL_ERROR) { // there was an error earlier. Causes JonDos to be kicked out when //prepareKickout is invoked but makes sure a control packet is still delivered //to the JonDo, before it triggers this kickout condition. if (a_bMessageToJAP && a_bControlMessage) { return returnKickout(pAccInfo); } else { pAccInfo->mutex->unlock(); return HANDLE_PACKET_PREPARE_FOR_CLOSING_CONNECTION; // don't let through messages from JAP } } if (a_bControlMessage) { pAccInfo->mutex->unlock(); return HANDLE_PACKET_CONNECTION_UNCHECKED; } else { // count the packet and continue checkings pAccInfo->transferredBytes += MIXPACKET_SIZE; pAccInfo->sessionPackets++; #ifdef SDTFA IncrementShmPacketCount(); #endif } /*if (pAccInfo->authFlags & AUTH_SENT_CC_REQUEST) { CAMsg::printMsg( LOG_DEBUG, "We already sent a CCRequest. Perhaps we should wait until client is able to deliver?\n"); }*/ /* UINT8 tmp[32]; //print64(tmp,pAccInfo->transferredBytes - m_countTransferred); //CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance1: Transferred bytes:%s\n", tmp); print64(tmp,pAccInfo->transferredBytes); CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance2: Transferred bytes:%s\n", tmp); print64(tmp,pAccInfo->confirmedBytes); CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance3: Confirmed bytes: %s\n", tmp); CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance3: Prepaid bytes: %d\n", getPrepaidBytes(pAccInfo)); */ // do the following tests after a lot of Mix packets only (gain speed...) if (!(pAccInfo->authFlags & (AUTH_TIMEOUT_STARTED | AUTH_HARD_LIMIT_REACHED | AUTH_ACCOUNT_EMPTY | AUTH_WAITING_FOR_FIRST_SETTLED_CC)) && pAccInfo->sessionPackets % PACKETS_BEFORE_NEXT_CHECK != 0) { //CAMsg::printMsg( LOG_DEBUG, "Now we gain some speed after %d session packets..., auth-flags: %x\n", pAccInfo->sessionPackets, pAccInfo->authFlags); pAccInfo->mutex->unlock(); return HANDLE_PACKET_CONNECTION_UNCHECKED; } /** @todo We need this trick so that the program does not freeze with active AI ThreadPool!!!! */ //pAccInfo->mutex->unlock(); SAVE_STACK("CAAccountingInstance::handleJapPacket", "before accounts hash"); if (pAccInfo->authFlags & AUTH_ACCOUNT_OK) { // this user is authenticated; test if he has logged in more than one time if (!ms_pInstance->m_currentAccountsHashtable) { // accounting instance is dying... return returnKickout(pAccInfo); } ms_pInstance->m_currentAccountsHashtable->getMutex()->lock(); loginEntry = (AccountLoginHashEntry*)ms_pInstance->m_currentAccountsHashtable->getValue(&(pAccInfo->accountNumber)); if (loginEntry) { pAccInfo->authFlags &= ~loginEntry->authRemoveFlags; //CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Remove flag: %d\n", loginEntry->authRemoveFlags); if (loginEntry->userID != pHashEntry->id) { // this is not the latest connection of this user; kick him out... pAccInfo->authFlags |= AUTH_MULTIPLE_LOGIN; ms_pInstance->m_currentAccountsHashtable->getMutex()->unlock(); return returnPrepareKickout(pAccInfo, new CAXMLErrorMessage(CAXMLErrorMessage::ERR_MULTIPLE_LOGIN, (UINT8*)"Only one login per account is allowed!")); } else if (loginEntry->authFlags & AUTH_OUTDATED_CC) { loginEntry->authFlags &= ~AUTH_OUTDATED_CC; UINT8 tmp[32]; print64(tmp,pAccInfo->accountNumber); CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Fixing bytes from outdated CC for account %s...\n", tmp); // we had stored an outdated CC; insert confirmed bytes from current CC here and also update client CAXMLCostConfirmation * pCC = NULL; bool bSettled; dbInterface = CAAccountingDBInterface::getConnection();//new CAAccountingDBInterface(); if(dbInterface != NULL) { dbInterface->getCostConfirmation(pAccInfo->accountNumber, ms_pInstance->m_currentCascade, &pCC, bSettled); CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } /*ms_pInstance->m_dbInterface->getCostConfirmation(pAccInfo->accountNumber, ms_pInstance->m_currentCascade, &pCC, bSettled);*/ if (pCC != NULL) { if (bSettled) { pAccInfo->transferredBytes += loginEntry->confirmedBytes - pAccInfo->confirmedBytes; pAccInfo->confirmedBytes = loginEntry->confirmedBytes; loginEntry->confirmedBytes = 0; pAccInfo->authFlags |= AUTH_SENT_CC_REQUEST; pAccInfo->pControlChannel->sendXMLMessage(pCC->getXMLDocument()); } else { CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: While trying to fix bytes from outdated CC," "another CC was received! Waiting for settlement... \n"); } delete pCC; pCC = NULL; } else { CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: Bytes from outdated CC could not be fixed!\n"); } } else if (loginEntry->authFlags & AUTH_ACCOUNT_EMPTY) { // Do not reset the flag, so that the confirmedBytes are always reset. //loginEntry->authFlags &= ~AUTH_ACCOUNT_EMPTY; pAccInfo->authFlags |= AUTH_ACCOUNT_EMPTY; /* confirmedBytes = 0 leads to immediate disconnection. * If confirmedBytes > 0, any remaining prepaid bytes may be used. */ pAccInfo->confirmedBytes = loginEntry->confirmedBytes; CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: Account is empty!\n"); } else if (loginEntry->authFlags & AUTH_INVALID_ACCOUNT) { loginEntry->authFlags &= ~AUTH_INVALID_ACCOUNT; CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Found invalid account! Kicking out user...\n"); err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_KEY_NOT_FOUND); } else if (loginEntry->authFlags & AUTH_BLOCKED) { loginEntry->authFlags &= ~AUTH_BLOCKED; CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Kicking out blocked user!\n"); err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_BLOCKED); } else if (loginEntry->authFlags & AUTH_DATABASE) { loginEntry->authFlags &= ~AUTH_DATABASE; CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Upps - kicking out user due to database error...\n"); err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_DATABASE_ERROR); } else if (loginEntry->authFlags & AUTH_UNKNOWN) { loginEntry->authFlags &= ~AUTH_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Unknown error! Kicking out user...\n"); err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR); } } else { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: handleJapPacket did not find user login hash entry!\n"); //pAccInfo->sessionPackets = 0; return returnKickout(pAccInfo); } ms_pInstance->m_currentAccountsHashtable->getMutex()->unlock(); } if (pAccInfo->authFlags & AUTH_ACCOUNT_EMPTY) { // There should be no time limit. The connections is simply closed after all prepaid bytes are gone. pAccInfo->lastHardLimitSeconds = time(NULL); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Account empty with %d prepaid bytes!\n", getPrepaidBytes(pAccInfo)); #endif if (getPrepaidBytes(pAccInfo) <= 0) { CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Account empty! Kicking out user...\n"); err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_ACCOUNT_EMPTY); } else { /** * Do not make further checkings. Let the client use the * remaining prepaid bytes, and then disconnect him afterwards. * As the confirmedBytes are set to zero when the client connects and * the account has been empty before, no other (unauthenticated) * client may use these bytes. */ returnOK(pAccInfo); } } /** @todo We need this trick so that the program does not freeze with active AI ThreadPool!!!! */ //pAccInfo->mutex->lock(); SAVE_STACK("CAAccountingInstance::handleJapPacket", "before err"); if (err) { return returnPrepareKickout(pAccInfo, err); } //CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: handleJapPacket auth for account %s.\n", accountNrAsString); if (!(pAccInfo->authFlags & AUTH_GOT_ACCOUNTCERT)) { //dont let the packet through for now, but still wait for an account cert if (!(pAccInfo->authFlags & AUTH_TIMEOUT_STARTED)) { pAccInfo->authFlags |= AUTH_TIMEOUT_STARTED; pAccInfo->authTimeoutStartSeconds = time(NULL); CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Wait for account certificate: %u\n", pAccInfo->authTimeoutStartSeconds); } //kick user out if a timeout was set and has since run out if (time(NULL) > pAccInfo->authTimeoutStartSeconds + AUTH_TIMEOUT) { //#ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Auth timeout has runout, will kick out user now...\n"); //#endif return returnPrepareKickout(pAccInfo, new CAXMLErrorMessage(CAXMLErrorMessage::ERR_NO_ACCOUNTCERT)); } pAccInfo->mutex->unlock(); return HANDLE_PACKET_HOLD_CONNECTION; } else { if(pAccInfo->authFlags & AUTH_FAKE ) { // authentication process not properly finished #ifdef DEBUG CAMsg::printMsg( LOG_DEBUG, "AccountingInstance: AUTH_FAKE flag is set ... byebye\n"); #endif return returnPrepareKickout(pAccInfo, new CAXMLErrorMessage(CAXMLErrorMessage::ERR_BAD_SIGNATURE, (UINT8*)"Your account certificate is invalid")); } else if (pAccInfo->authFlags & AUTH_MULTIPLE_LOGIN) { return returnPrepareKickout(pAccInfo, new CAXMLErrorMessage(CAXMLErrorMessage::ERR_MULTIPLE_LOGIN, (UINT8*)"Only one login per account is allowed!")); } if( !(pAccInfo->authFlags & AUTH_ACCOUNT_OK) ) { // we did not yet receive the response to the challenge... if(time(NULL) >= pAccInfo->challengeSentSeconds + CHALLENGE_TIMEOUT) { CAMsg::printMsg( LOG_DEBUG, "AccountingInstance: Jap refused to send response to challenge (Request Timeout)...\n"); return returnPrepareKickout(pAccInfo, new CAXMLErrorMessage(CAXMLErrorMessage::ERR_NO_ACCOUNTCERT)); //timeout over -> kick out } else //timeout still running { pAccInfo->mutex->unlock(); // do not forward any traffic from JAP return HANDLE_PACKET_HOLD_CONNECTION; } } //---------------------------------------------------------- // ****** Hardlimit cost confirmation check ********** //counting unconfirmed bytes is not necessary anymore, since we deduct from prepaid bytes //UINT32 unconfirmedBytes=diff64(pAccInfo->transferredBytes,pAccInfo->confirmedBytes); //confirmed and transferred bytes are cumulative, so they use UINT64 to store potentially huge values //prepaid Bytes as the difference will be much smaller, but might be negative, so we cast to signed int SINT32 prepaidBytes = getPrepaidBytes(pAccInfo); /* if (prepaidBytes < m_prepaidBytesMinimum) { // this is only for logging the typical client behaviour in confirming prepaid bytes m_prepaidBytesMinimum = prepaidBytes; CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: New PrepaidBytes minimum: %d\n", m_prepaidBytesMinimum); }*/ //CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: Prepaid bytes: %d!\n", prepaidBytes); if (prepaidBytes < 0 || prepaidBytes <= ms_pInstance->m_iHardLimitBytes) { UINT32 prepaidInterval = pglobalOptions->getPrepaidInterval(); if ((pAccInfo->authFlags & AUTH_HARD_LIMIT_REACHED) == 0) { pAccInfo->lastHardLimitSeconds = time(NULL); pAccInfo->authFlags |= AUTH_HARD_LIMIT_REACHED; } #ifdef DEBUG CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: Hard limit of %d bytes triggered in %d seconds \n", ms_pInstance->m_iHardLimitBytes, (pAccInfo->lastHardLimitSeconds + HARD_LIMIT_TIMEOUT - time(NULL))); #endif /* @todo: we don't use prepaid interval hard limit because it may abort * large downloads/uploads, where large amounts of data are handled by mixes * in a short time. */ if ( ( (time(NULL) >= pAccInfo->lastHardLimitSeconds + HARD_LIMIT_TIMEOUT) && (prepaidBytes <= 0) ) || (prepaidBytes < 0 && (UINT32)(prepaidBytes * (-1)) >= prepaidInterval) ) { //#ifdef DEBUG char* strReason; if (time(NULL) >= pAccInfo->lastHardLimitSeconds + HARD_LIMIT_TIMEOUT) { strReason = "timeout"; } else { strReason = "negative prepaid interval exceeded"; } CAMsg::printMsg( LOG_INFO, "Accounting instance: User refused " "to send cost confirmation (HARDLIMIT EXCEEDED, %s). " "PrepaidBytes were: %d\n", strReason, prepaidBytes); //#endif //ms_pInstance->m_pIPBlockList->insertIP( pHashEntry->peerIP ); pAccInfo->lastHardLimitSeconds = 0; return returnPrepareKickout(pAccInfo, new CAXMLErrorMessage(CAXMLErrorMessage::ERR_NO_CONFIRMATION)); } else { if( !(pAccInfo->authFlags & AUTH_SENT_CC_REQUEST) ) { sendCCRequest(pAccInfo); } pAccInfo->mutex->unlock(); // do not forward any traffic from JAP return HANDLE_PACKET_HOLD_CONNECTION; } } else { pAccInfo->authFlags &= ~AUTH_HARD_LIMIT_REACHED; } //------------------------------------------------------- // *** SOFT LIMIT CHECK *** is it time to request a new cost confirmation? if ( prepaidBytes < 0 || prepaidBytes <= ms_pInstance->m_iSoftLimitBytes ) { #ifdef DEBUG CAMsg::printMsg(LOG_ERR, "soft limit of %d bytes triggered \n",ms_pInstance->m_iSoftLimitBytes); #endif if( (pAccInfo->authFlags & AUTH_SENT_CC_REQUEST) ) {//we have sent a first CC request //still waiting for the answer to the CC reqeust //CAMsg::printMsg(LOG_ERR, "Waiting for CC request for account nr %u\n", pAccInfo->accountNumber); return returnOK(pAccInfo); }//we have sent a CC request // no CC request sent yet --> send a first CC request //send CC to jap sendCCRequest(pAccInfo); return returnOK(pAccInfo); }// end of soft limit exceeded //everything is fine! let the packet pass thru return returnOK(pAccInfo); } //end of AUTH_GOT_ACCOUNTCERT } /******************************************************************/ //methods to provide a unified point of exit for handleJapPacket /******************************************************************/ SINT32 CAAccountingInstance::getPrepaidBytes(tAiAccountingInfo* pAccInfo) { if (pAccInfo == NULL) { return 0; } SINT32 prepaidBytes; #ifdef DEBUG CAMsg::printMsg(LOG_INFO, "Calculating TransferredBytes: %Lu ConfirmedBytes: %Lu\n", pAccInfo->transferredBytes, pAccInfo->confirmedBytes); #endif if (pAccInfo->confirmedBytes > pAccInfo->transferredBytes) { prepaidBytes = pAccInfo->confirmedBytes - pAccInfo->transferredBytes; if (prepaidBytes < 0) { // PrepaidBytes should be greater than 0 !!! UINT8 tmp[32], tmp2[32]; print64(tmp,pAccInfo->transferredBytes); print64(tmp2,pAccInfo->confirmedBytes); CAMsg::printMsg(LOG_CRIT, "PrepaidBytes are way to high! Maybe a hacker attack? Or CC did get lost?\n"); CAMsg::printMsg(LOG_INFO, "TransferredBytes: %s ConfirmedBytes: %s\n", tmp, tmp2); UINT32 prepaidInterval = pglobalOptions->getPrepaidInterval(); prepaidBytes = (SINT32)prepaidInterval; pAccInfo->transferredBytes = pAccInfo->confirmedBytes - prepaidInterval; } } else { prepaidBytes = pAccInfo->transferredBytes - pAccInfo->confirmedBytes; prepaidBytes *= -1; } return prepaidBytes; } /** * everything is fine, let the packet pass */ SINT32 CAAccountingInstance::returnOK(tAiAccountingInfo* pAccInfo) { SINT32 ret; if (pAccInfo->authFlags & AUTH_WAITING_FOR_FIRST_SETTLED_CC) { //CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Still no settled CC...\n"); // it is not yet sure whether this user has a charged account ret = HANDLE_PACKET_HOLD_CONNECTION; } else { ret = HANDLE_PACKET_CONNECTION_OK; } pAccInfo->mutex->unlock(); return ret; } /** * When receiving this message, the Mix should kick the user out immediately */ SINT32 CAAccountingInstance::returnKickout(tAiAccountingInfo* pAccInfo) { UINT8 tmp[32]; print64(tmp,pAccInfo->accountNumber); CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: should kick out user with account %s now...\n", tmp); pAccInfo->transferredBytes = pAccInfo->confirmedBytes; pAccInfo->mutex->unlock(); return HANDLE_PACKET_CLOSE_CONNECTION; } /* * hold packet, no timeout started * (Usage: send an error message before kicking out the user: * sets AUTH_FATAL_ERROR ) * IMPORTANT: You need to hold a lock for pAccInfo->mutex when invoking this. * Postcondition is that pAccInfo->mutex is unlocked. */ SINT32 CAAccountingInstance::returnPrepareKickout(tAiAccountingInfo* pAccInfo, CAXMLErrorMessage* a_error) { pAccInfo->authFlags |= AUTH_FATAL_ERROR; if (a_error) { //CAMsg::printMsg(LOG_CRIT, "AccountingInstance: Sending error message...\n"); XERCES_CPP_NAMESPACE::DOMDocument* doc=NULL; a_error->toXmlDocument(doc); delete a_error; a_error = NULL; //pAccInfo->sessionPackets = 0; // allow some pakets to pass by to send the control message pAccInfo->pControlChannel->sendXMLMessage(doc); if (doc != NULL) { doc->release(); doc = NULL; } } else { CAMsg::printMsg(LOG_CRIT, "AccountingInstance: Should send error message, but none is available!\n"); } pAccInfo->mutex->unlock(); return HANDLE_PACKET_PREPARE_FOR_CLOSING_CONNECTION; } SINT32 CAAccountingInstance::sendCCRequest(tAiAccountingInfo* pAccInfo) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::sendCCRequest"); XERCES_CPP_NAMESPACE::DOMDocument* doc=NULL; UINT32 prepaidInterval = pglobalOptions->getPrepaidInterval(); pAccInfo->authFlags |= AUTH_SENT_CC_REQUEST; if (pAccInfo->authFlags & AUTH_ACCOUNT_EMPTY) { // do not send further CC requests for this account return E_SUCCESS; } // prepaid bytes are "confirmed bytes - transfered bytes" //UINT64 bytesToConfirm = pAccInfo->confirmedBytes + (prepaidInterval) - (pAccInfo->confirmedBytes - pAccInfo->transferredBytes); pAccInfo->bytesToConfirm = (prepaidInterval) + pAccInfo->transferredBytes; makeCCRequest(pAccInfo->accountNumber, pAccInfo->bytesToConfirm, doc); //pAccInfo->authFlags |= AUTH_SENT_CC_REQUEST; #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CC request sent for %Lu bytes \n",pAccInfo->bytesToConfirm); CAMsg::printMsg(LOG_DEBUG, "transferrred bytes: %Lu bytes \n",pAccInfo->transferredBytes); CAMsg::printMsg(LOG_DEBUG, "prepaid Interval: %u \n",prepaidInterval); UINT32 debuglen = 3000; UINT8 debugout[3000]; DOM_Output::dumpToMem(doc,debugout,&debuglen); debugout[debuglen] = 0; CAMsg::printMsg(LOG_DEBUG, "the CC sent looks like this: %s \n",debugout); #endif //FINISH_STACK("CAAccountingInstance::sendCCRequest"); SINT32 ret = pAccInfo->pControlChannel->sendXMLMessage(doc); if (doc != NULL) { doc->release(); doc = NULL; } return ret; } bool CAAccountingInstance::cascadeMatchesCC(CAXMLCostConfirmation *pCC) { UINT8* certHash; if(m_allHashesLen != pCC->getNumberOfHashes() ) { return false; } for (UINT32 i = 0; i < pCC->getNumberOfHashes(); i++) { certHash = pCC->getPriceCertHash(i); if ((certHash = (UINT8*)m_certHashCC->getValue(certHash)) != NULL) { #ifdef DEBUG CAMsg::printMsg( LOG_INFO, "CC1: %s\n", certHash); #endif } else { #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CC do not match current cascade.\n"); #endif return false; } } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CC matches current Cascade.\n"); #endif return true; } /** * creating the xml of a new CC is really the responsability of the CAXMLCostConfirmation class * knowledge about the structure of a CC's XML should be encapsulated in it * TODO: add constructor to that class that takes accountnumber, transferredbytes etc as params * (should use a template internally into which it only inserts accNumber and bytes,to speed things up * TODO: add toXMLElement method * then replace manually building the xml here with contructing a CAXMLCostConfirmation * and just add the xml returned by its toXMLElement method * @param callingMix: the Mix instance to which the AI belongs * (needed to get cascadeInfo to extract the price certificates to include in cost confirmations) */ SINT32 CAAccountingInstance::prepareCCRequest(CAMix* callingMix, UINT8* a_AiName) { m_preparedCCRequest = createDOMDocument(); DOMElement* elemRoot = createDOMElement(m_preparedCCRequest,"PayRequest"); setDOMElementAttribute(elemRoot,"version",(UINT8*) "1.0"); m_preparedCCRequest->appendChild(elemRoot); DOMElement* elemCC = createDOMElement(m_preparedCCRequest,"CC"); setDOMElementAttribute(elemCC,"version",(UINT8*) "1.2"); elemRoot->appendChild(elemCC); DOMElement* elemAiName = createDOMElement(m_preparedCCRequest,"AiID"); setDOMElementValue(elemAiName, a_AiName); elemCC->appendChild(elemAiName); //extract price certificate elements from cascadeInfo //get cascadeInfo from CAMix(which makeCCRequest needs to extract the price certs XERCES_CPP_NAMESPACE::DOMDocument* cascadeInfoDoc=NULL; callingMix->getMixCascadeInfo(cascadeInfoDoc); DOMElement* cascadeInfoElem = cascadeInfoDoc->getDocumentElement(); DOMNodeList* allMixes = getElementsByTagName(cascadeInfoElem,"Mix"); UINT32 nrOfMixes = allMixes->getLength(); DOMNode** mixNodes = new DOMNode*[nrOfMixes]; //so we can use separate loops for extracting, hashing and appending DOMNode* curMixNode=NULL; for (UINT32 i = 0, j = 0, count = nrOfMixes; i < count; i++, j++){ //cant use getDOMChildByName from CAUtil here yet, since it will always return the first child curMixNode = allMixes->item(i); if (getDOMChildByName(curMixNode,"PriceCertificate",mixNodes[j],true) != E_SUCCESS) { j--; nrOfMixes--; } } //hash'em, and get subjectkeyidentifiers UINT8 digest[SHA_DIGEST_LENGTH]; m_allHashes=new UINT8*[nrOfMixes]; m_allHashesLen = nrOfMixes; UINT8** allSkis=new UINT8*[nrOfMixes]; DOMNode* skiNode=NULL; for (UINT32 i = 0; i < nrOfMixes; i++){ UINT8* out=new UINT8[5000]; UINT32 outlen=5000; DOM_Output::makeCanonical(mixNodes[i],out,&outlen); out[outlen] = 0; #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "price cert to be hashed: %s",out); #endif SHA1(out,outlen,digest); delete[] out; out = NULL; UINT8* tmpBuff = new UINT8[1024]; UINT32 len=1024; if(CABase64::encode(digest,SHA_DIGEST_LENGTH,tmpBuff,&len)!=E_SUCCESS) return E_UNKNOWN; tmpBuff[len]=0; //line breaks might have been added, and would lead to database problems strtrim(tmpBuff); //return value ohny significant for NULL or all-whitespace string, ignore m_allHashes[i] = tmpBuff; //do not delete tmpBuff here, since we're using allHashes below if (getDOMChildByName(mixNodes[i],"SubjectKeyIdentifier",skiNode,true) != E_SUCCESS) { CAMsg::printMsg(LOG_CRIT,"Could not get mix id from price cert"); } allSkis[i] = (UINT8*) XMLString::transcode(skiNode->getFirstChild()->getNodeValue()); } //concatenate the hashes, and store for future reference to indentify the cascade m_currentCascade = new UINT8[256]; memset(m_currentCascade, 0, (sizeof(UINT8)*256 )); for (UINT32 j = 0; j < nrOfMixes; j++) { //check for hash value size (should always be OK) if (strlen((const char*)m_currentCascade) > ( 256 - strlen((const char*)m_allHashes[j]) ) ) { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance::prepareCCRequest: " "Too many/too long hash values, ran out of allocated memory\n"); return E_UNKNOWN; } if (j == 0) { m_currentCascade = (UINT8*) strcpy( (char*) m_currentCascade,(const char*)m_allHashes[j]); } else { m_currentCascade = (UINT8*) strcat((char*)m_currentCascade,(char*)m_allHashes[j]); } } //and append to CC DOMElement* elemPriceCerts = createDOMElement(m_preparedCCRequest,"PriceCertificates"); DOMElement* elemCert=NULL; for (UINT32 i = 0; i < nrOfMixes; i++) { elemCert = createDOMElement(m_preparedCCRequest,"PriceCertHash"); //CAMsg::printMsg(LOG_DEBUG,"hash to be inserted in cc: index %d, value %s\n",i,m_allHashes[i]); setDOMElementValue(elemCert,m_allHashes[i]); //delete[] allHashes[i]; setDOMElementAttribute(elemCert,"id",allSkis[i]); setDOMElementAttribute(elemCert, "position", i); if (i == 0) { setDOMElementAttribute(elemCert,"isAI",(UINT8*)"true"); } elemPriceCerts->appendChild(elemCert); } elemCC->appendChild(elemPriceCerts); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "finished method makeCCRequest\n"); #endif delete[] mixNodes; mixNodes = NULL; //delete[] allHashes; delete[] allSkis; allSkis = NULL; return E_SUCCESS; } SINT32 CAAccountingInstance::makeCCRequest(const UINT64 accountNumber, const UINT64 transferredBytes, XERCES_CPP_NAMESPACE::DOMDocument* & doc) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::makeCCRequest"); DOMNode* elemCC=NULL; doc = createDOMDocument(); doc->appendChild(doc->importNode(m_preparedCCRequest->getDocumentElement(),true)); getDOMChildByName(doc->getDocumentElement(),"CC",elemCC); DOMElement* elemAccount = createDOMElement(doc,"AccountNumber"); setDOMElementValue(elemAccount, accountNumber); elemCC->appendChild(elemAccount); DOMElement* elemBytes = createDOMElement(doc,"TransferredBytes"); setDOMElementValue(elemBytes, transferredBytes); elemCC->appendChild(elemBytes); FINISH_STACK("CAAccountingInstance::makeCCRequest"); return E_SUCCESS; } SINT32 CAAccountingInstance::sendAILoginConfirmation(tAiAccountingInfo* pAccInfo, const UINT32 code, UINT8 * message) { SINT32 sendSuccess = E_SUCCESS; XERCES_CPP_NAMESPACE::DOMDocument* doc = createDOMDocument(); DOMElement *elemRoot = createDOMElement(doc, "LoginConfirmation"); setDOMElementAttribute(elemRoot, "code", code); setDOMElementValue(elemRoot, message); doc->appendChild(elemRoot); #ifdef DEBUG UINT32 debuglen = 3000; UINT8 debugout[3000]; DOM_Output::dumpToMem(doc,debugout,&debuglen); debugout[debuglen] = 0; CAMsg::printMsg(LOG_DEBUG, "the AILogin Confirmation sent looks like this: %s \n",debugout); #endif sendSuccess = pAccInfo->pControlChannel->sendXMLMessage(doc); if (doc != NULL) { doc->release(); doc = NULL; } return sendSuccess; } /** * Handle a user (xml) message sent to us by the Jap. * * This function is running inside the AiThread. It determines * what type of message we have and calls the appropriate handle...() * function */ SINT32 CAAccountingInstance::processJapMessage(fmHashTableEntry * pHashEntry,const XERCES_CPP_NAMESPACE::DOMDocument* a_DomDoc) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::processJapMessage"); if (pHashEntry == NULL) { return E_UNKNOWN; } DOMElement* root = a_DomDoc->getDocumentElement(); if(root == NULL) { CAMsg::printMsg(LOG_DEBUG, "ProcessJapMessage: getDocument Element is null!!!\n" ); return E_UNKNOWN; } char* docElementName = XMLString::transcode(root->getTagName()); aiQueueItem* pItem=NULL; void (CAAccountingInstance::*handleFunc)(tAiAccountingInfo*,DOMElement*) = NULL; SINT32 ret, hf_ret = 0; // what type of message is it? if ( strcmp( docElementName, "AccountCertificate" ) == 0 ) { #ifdef DEBUG CAMsg::printMsg( LOG_DEBUG, "Received an AccountCertificate. Calling handleAccountCertificate()\n" ); #endif //handleFunc = &CAAccountingInstance::handleAccountCertificate; hf_ret = ms_pInstance->handleAccountCertificate( pHashEntry->pAccountingInfo, root ); processJapMessageLoginHelper(pHashEntry, hf_ret, false); } else if ( strcmp( docElementName, "Response" ) == 0) { #ifdef DEBUG CAMsg::printMsg( LOG_DEBUG, "Received a Response (challenge-response)\n" ); #endif //handleFunc = &CAAccountingInstance::handleChallengeResponse; hf_ret = ms_pInstance->handleChallengeResponse( pHashEntry->pAccountingInfo, root ); processJapMessageLoginHelper(pHashEntry, hf_ret, false); if(hf_ret == CAXMLErrorMessage::ERR_OK) { CAMsg::printMsg( LOG_DEBUG, "Prepaid bytes are: %d\n", getPrepaidBytes(pHashEntry->pAccountingInfo)); pHashEntry->pAccountingInfo->authFlags |= (getPrepaidBytes(pHashEntry->pAccountingInfo) > 0) ? AUTH_LOGIN_SKIP_SETTLEMENT : AUTH_NEW; } } else if ( strcmp( docElementName, "CC" ) == 0 ) { #ifdef DEBUG CAMsg::printMsg( LOG_DEBUG, "Received a CC. Calling handleCostConfirmation()\n" ); #endif //handleFunc = &CAAccountingInstance::handleCostConfirmation; hf_ret = ms_pInstance->handleCostConfirmation( pHashEntry->pAccountingInfo, root ); processJapMessageLoginHelper(pHashEntry, hf_ret, true); } else { CAMsg::printMsg( LOG_ERR, "AI Received XML message with unknown root element \"%s\". This is not accepted!\n", docElementName ); SAVE_STACK("CAAccountingInstance::processJapMessage", "error"); XMLString::release(&docElementName); return E_UNKNOWN; } XMLString::release(&docElementName); /** @todo this does not work yet due to errors in CAMutex!!! if (handleFunc) { pItem = new aiQueueItem; pItem->pDomDoc = new DOM_Document(a_DomDoc); pItem->pAccInfo = pHashEntry->pAccountingInfo; pItem->handleFunc = handleFunc; pHashEntry->pAccountingInfo->mutex->lock(); pItem->pAccInfo->nrInQueue++; ret = ms_pInstance->m_aiThreadPool->addRequest(processThread, pItem); if (ret !=E_SUCCESS) { pItem->pAccInfo->nrInQueue--; CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: Process could not add to AI thread pool!\n" ); delete pItem->pDomDoc; delete pItem; } pHashEntry->pAccountingInfo->mutex->unlock(); return ret; }*/ // remove these lines if AI thread pool is used (see @todo above) //(ms_pInstance->*handleFunc)(pHashEntry->pAccountingInfo, root ); FINISH_STACK("CAAccountingInstance::processJapMessage"); return E_SUCCESS; } void CAAccountingInstance::processJapMessageLoginHelper(fmHashTableEntry *pHashEntry, UINT32 handlerReturnValue, bool lastLoginMessage) { if(pHashEntry->pAccountingInfo != NULL) { if(pHashEntry->pAccountingInfo->mutex == NULL) { return; } pHashEntry->pAccountingInfo->mutex->lock(); if(pHashEntry->pAccountingInfo->authFlags & AUTH_LOGIN_NOT_FINISHED) { if(handlerReturnValue != CAXMLErrorMessage::ERR_OK) { pHashEntry->pAccountingInfo->authFlags &= ~AUTH_LOGIN_NOT_FINISHED; pHashEntry->pAccountingInfo->authFlags |= AUTH_LOGIN_FAILED; CAXMLErrorMessage *err = NULL; XERCES_CPP_NAMESPACE::DOMDocument *errDoc = NULL; if(pHashEntry->pAccountingInfo->authFlags & AUTH_BLOCKED ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_BLOCKED, (UINT8 *) "AI login: access denied because your account is blocked"); } else if(pHashEntry->pAccountingInfo->authFlags & AUTH_ACCOUNT_EMPTY ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_ACCOUNT_EMPTY, (UINT8 *) "AI login: access denied because your account is empty"); } else if(pHashEntry->pAccountingInfo->authFlags & AUTH_INVALID_ACCOUNT ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_NO_BALANCE, (UINT8 *) "AI login: access denied because your account is not valid"); } else if(pHashEntry->pAccountingInfo->authFlags & AUTH_FAKE ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_WRONG_DATA, (UINT8*)"Your CostConfirmation has a wrong number of transferred bytes"); } else { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR, (UINT8 *) "AI login: error occured while connecting, access denied"); } if(err != NULL) { err->toXmlDocument(errDoc); pHashEntry->pAccountingInfo->pControlChannel->sendXMLMessage(errDoc); delete err; err = NULL; } if(errDoc != NULL) { errDoc->release(); errDoc = NULL; } /*sendAILoginConfirmation(pHashEntry->pAccountingInfo, CAXMLErrorMessage::ERR_BLOCKED, (UINT8*) "AI access denied");*/ } else if(lastLoginMessage) { //CAMsg::printMsg( LOG_ERR, "User successfully logged in\n"); pHashEntry->pAccountingInfo->authFlags &= ~AUTH_LOGIN_NOT_FINISHED; } } pHashEntry->pAccountingInfo->mutex->unlock(); } } SINT32 CAAccountingInstance::loginProcessStatus(fmHashTableEntry *pHashEntry) { SINT32 ret = 0; if(pHashEntry == NULL) { return ret |= AUTH_LOGIN_FAILED; } if(pHashEntry->pAccountingInfo == NULL) { return ret |= AUTH_LOGIN_FAILED; } if(pHashEntry->pAccountingInfo->mutex == NULL) { return ret |= AUTH_LOGIN_FAILED; } pHashEntry->pAccountingInfo->mutex->lock(); ret = pHashEntry->pAccountingInfo->authFlags & (AUTH_LOGIN_NOT_FINISHED | AUTH_LOGIN_FAILED | AUTH_LOGIN_SKIP_SETTLEMENT); pHashEntry->pAccountingInfo->mutex->unlock(); return ret; } SINT32 CAAccountingInstance::finishLoginProcess(fmHashTableEntry *pHashEntry) { SINT32 ret = 0; UINT64 accountNumber = 0; UINT32 authFlags = 0; AccountLoginHashEntry *loginEntry; tAiAccountingInfo* pAccInfo = pHashEntry->pAccountingInfo; if(ms_pInstance==NULL) { return ret |= AUTH_LOGIN_FAILED; } if(ms_pInstance->m_currentAccountsHashtable == NULL) { return ret |= AUTH_LOGIN_FAILED; } if(ms_pInstance->m_currentAccountsHashtable->getMutex() == NULL) { return ret |= AUTH_LOGIN_FAILED; } if(pHashEntry == NULL) { return ret |= AUTH_LOGIN_FAILED; } if(pHashEntry->pAccountingInfo == NULL) { return ret |= AUTH_LOGIN_FAILED; } if(pHashEntry->pAccountingInfo->mutex == NULL) { return ret |= AUTH_LOGIN_FAILED; } pAccInfo->mutex->lock(); accountNumber = pAccInfo->accountNumber; pAccInfo->mutex->unlock(); ms_pInstance->m_currentAccountsHashtable->getMutex()->lock(); loginEntry = (AccountLoginHashEntry*)ms_pInstance->m_currentAccountsHashtable->getValue(&accountNumber); if (loginEntry) { authFlags = loginEntry->authFlags; ret |= (loginEntry->authFlags & (AUTH_INVALID_ACCOUNT | AUTH_BLOCKED | AUTH_ACCOUNT_EMPTY)); ret |= (ret==0) ? 0 : AUTH_LOGIN_FAILED; } else { ret |= (AUTH_LOGIN_FAILED | AUTH_INVALID_ACCOUNT); } /*ret = pHashEntry->pAccountingInfo->authFlags & (AUTH_LOGIN_NOT_FINISHED | AUTH_LOGIN_FAILED);*/ ms_pInstance->m_currentAccountsHashtable->getMutex()->unlock(); if(ret) { CAXMLErrorMessage *err = NULL; XERCES_CPP_NAMESPACE::DOMDocument *errDoc = NULL; /* Instead of using special login confirmation messages * we rather send XMLErrorMessages for backward compatibility reasons * because old JAPs (version <= 00.09.021) can handle them */ CAMsg::printMsg(LOG_DEBUG, "Finishing AI login with an error message for the client, flags: %x\n",loginEntry->authFlags); if(authFlags & AUTH_BLOCKED ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_BLOCKED, (UINT8 *) "AI login: access denied because your account is blocked"); } else if(authFlags & AUTH_ACCOUNT_EMPTY ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_ACCOUNT_EMPTY, (UINT8 *) "AI login: access denied because your account is empty"); } else if(authFlags & AUTH_INVALID_ACCOUNT ) { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_NO_BALANCE, (UINT8 *) "AI login: access denied because your account is not valid"); } else { err = new CAXMLErrorMessage(CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR, (UINT8 *) "AI login: error occured while connecting, access denied"); } if(err != NULL) { err->toXmlDocument(errDoc); pHashEntry->pAccountingInfo->pControlChannel->sendXMLMessage(errDoc); delete err; err = NULL; } if(errDoc != NULL) { errDoc->release(); errDoc = NULL; } /*sendAILoginConfirmation(pAccInfo, CAXMLErrorMessage::ERR_BLOCKED, (UINT8*) "AI access denied");*/ } else { //send login confirmation to user, but if the message could not be send, login will fail /* These login confirmation messages are necessary for the new AI login protocol to indicate * that the process is finished after a settlement. * They won't bother old JAPs (version <= 00.09.021) because they will ignore * these confirmations. */ if(sendAILoginConfirmation(pAccInfo, CAXMLErrorMessage::ERR_OK, (UINT8*) "AI login successful") != E_SUCCESS) { ret |= AUTH_LOGIN_FAILED; } } return ret; } UINT32 CAAccountingInstance::handleAccountCertificate(tAiAccountingInfo* pAccInfo, DOMElement* root) { return handleAccountCertificate_internal(pAccInfo, root); INIT_STACK; FINISH_STACK("CAAccountingInstance::handleAccountCertificate"); } /** * Handles an account certificate of a newly connected Jap. * Parses accountnumber and publickey, checks the signature * and generates and sends a challenge XML structure to the * Jap. * TODO: think about switching account without changing mixcascade * (receive a new acc.cert. though we already have one) */ UINT32 CAAccountingInstance::handleAccountCertificate_internal(tAiAccountingInfo* pAccInfo, DOMElement* root) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::handleAccountCertificate"); //CAMsg::printMsg( LOG_ERR, "CAAccountingInstance::handleAccountCertificate start\n"); //CAMsg::printMsg(LOG_DEBUG, "started method handleAccountCertificate\n"); DOMElement* elGeneral=NULL; timespec now; getcurrentTime(now); // check authstate of this user if (pAccInfo == NULL) { return CAXMLErrorMessage::ERR_NO_RECORD_FOUND; } pAccInfo->mutex->lock(); if (pAccInfo->authFlags & AUTH_DELETE_ENTRY) { pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_NO_ERROR_GIVEN; } if (pAccInfo->authFlags & AUTH_GOT_ACCOUNTCERT) { //#ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Already got an account cert. Ignoring..."); //#endif CAXMLErrorMessage err( CAXMLErrorMessage::ERR_BAD_REQUEST, (UINT8*)"You have already sent an Account Certificate" ); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_BAD_REQUEST; } // parse & set accountnumber if (getDOMChildByName( root, "AccountNumber", elGeneral, false ) != E_SUCCESS || getDOMElementValue( elGeneral, pAccInfo->accountNumber ) != E_SUCCESS) { CAMsg::printMsg( LOG_ERR, "AccountCertificate has wrong or no accountnumber. Ignoring...\n"); CAXMLErrorMessage err(CAXMLErrorMessage::ERR_WRONG_FORMAT); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_WRONG_FORMAT; } // parse & set payment instance id UINT32 len=256; pAccInfo->pstrBIID=new UINT8[256]; if ( getDOMChildByName( root,"BiID", elGeneral, false ) != E_SUCCESS || getDOMElementValue( elGeneral,pAccInfo->pstrBIID, &len ) != E_SUCCESS) { delete[] pAccInfo->pstrBIID; pAccInfo->pstrBIID = NULL; CAMsg::printMsg( LOG_ERR, "AccountCertificate has no Payment Instance ID. Ignoring...\n"); CAXMLErrorMessage err(CAXMLErrorMessage::ERR_WRONG_FORMAT); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_WRONG_FORMAT; } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Stored payment instance ID: %s\n", pAccInfo->pstrBIID); #endif // parse & set public key if ( getDOMChildByName( root, "JapPublicKey", elGeneral, false ) != E_SUCCESS ) { CAMsg::printMsg( LOG_ERR, "AccountCertificate contains no public key. Ignoring...\n"); CAXMLErrorMessage err(CAXMLErrorMessage::ERR_KEY_NOT_FOUND); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_KEY_NOT_FOUND; } #ifdef DEBUG UINT8* aij; UINT32 aijsize; aij = DOM_Output::dumpToMem(elGeneral, &aijsize); aij[aijsize-1]=0; CAMsg::printMsg( LOG_DEBUG, "Setting user public key %s>\n", aij ); delete[] aij; aij = NULL; #endif pAccInfo->pPublicKey = new CASignature(); if ( pAccInfo->pPublicKey->setVerifyKey( elGeneral ) != E_SUCCESS ) { CAXMLErrorMessage err(CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR; } if ((!m_pJpiVerifyingInstance) || (m_pJpiVerifyingInstance->verifyXML( root, (CACertStore *)NULL ) != E_SUCCESS )) { // signature invalid. mark this user as bad guy CAMsg::printMsg( LOG_INFO, "CAAccountingInstance::handleAccountCertificate(): Bad Jpi signature\n" ); pAccInfo->authFlags |= AUTH_FAKE | AUTH_GOT_ACCOUNTCERT | AUTH_TIMEOUT_STARTED; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_BAD_SIGNATURE; } UINT8 * arbChallenge; UINT8 b64Challenge[ 512 ]; UINT32 b64Len = 512; //CAMsg::printMsg(LOG_DEBUG, "Almost finished handleAccountCertificate, preparing challenge\n"); // generate random challenge data and Base64 encode it arbChallenge = new UINT8[222]; getRandom( arbChallenge, 222 ); CABase64::encode( arbChallenge, 222, b64Challenge, &b64Len ); delete[] pAccInfo->pChallenge; pAccInfo->pChallenge = arbChallenge; // store challenge for later.. // generate XML challenge structure XERCES_CPP_NAMESPACE::DOMDocument* doc = createDOMDocument(); DOMElement* elemRoot = createDOMElement(doc, "Challenge" ); DOMElement* elemPanic = createDOMElement(doc, "DontPanic" ); DOMElement* elemPrepaid = createDOMElement(doc, "PrepaidBytes" ); setDOMElementAttribute(elemPanic, "version",(UINT8*) "1.0" ); doc->appendChild( elemRoot ); elemRoot->appendChild( elemPanic ); elemRoot->appendChild( elemPrepaid ); setDOMElementValue( elemPanic, b64Challenge ); SINT32 prepaidAmount = 0; //m_dbInterface->getPrepaidAmount(pAccInfo->accountNumber, m_currentCascade, false); CAAccountingDBInterface *dbInterface = CAAccountingDBInterface::getConnection(); if(dbInterface != NULL) { prepaidAmount = dbInterface->getPrepaidAmount(pAccInfo->accountNumber, m_currentCascade, false); CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } /* EXPERIMENTAL: transmit negative prepaid bytes (but not less than -PREPAID_BYTES) */ SINT32 negPrepaidIval = (-1*(SINT32)pglobalOptions->getPrepaidInterval()); if (prepaidAmount < negPrepaidIval) { prepaidAmount = negPrepaidIval; } setDOMElementValue( elemPrepaid, prepaidAmount); // send XML struct to Jap & set auth flags pAccInfo->pControlChannel->sendXMLMessage(doc); if (doc != NULL) { doc->release(); doc = NULL; } pAccInfo->authFlags |= AUTH_CHALLENGE_SENT | AUTH_GOT_ACCOUNTCERT | AUTH_TIMEOUT_STARTED; pAccInfo->challengeSentSeconds = time(NULL); //CAMsg::printMsg("Last Account Certificate request seconds: for IP %u%u%u%u", (UINT8)pHashEntry->peerIP[0], (UINT8)pHashEntry->peerIP[1],(UINT8) pHashEntry->peerIP[2], (UINT8)pHashEntry->peerIP[3]); //CAMsg::printMsg( LOG_ERR, "CAAccountingInstance::handleAccountCertificate stop\n"); pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_OK; } UINT32 CAAccountingInstance::handleChallengeResponse(tAiAccountingInfo* pAccInfo, DOMElement* root) { return handleChallengeResponse_internal(pAccInfo, root); INIT_STACK; FINISH_STACK("CAAccountingInstance::handleChallengeResponse"); } /** * Handles the response to our challenge. * Checks the validity of the response and sets the user's authFlags * Also gets the last CC of the user, and sends it to the JAP * accordingly. */ UINT32 CAAccountingInstance::handleChallengeResponse_internal(tAiAccountingInfo* pAccInfo, DOMElement* root) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::handleChallengeResponse"); //CAMsg::printMsg( LOG_ERR, "CAAccountingInstance::handleChallengeResponse start\n"); UINT8 decodeBuffer[ 512 ]; UINT32 decodeBufferLen = 512; UINT32 usedLen; DOMElement* elemPanic=NULL; DSA_SIG * pDsaSig=NULL; SINT32 prepaidAmount = 0; AccountLoginHashEntry* loginEntry; CAXMLCostConfirmation* pCC = NULL; bool bSendCCRequest = true; UINT32 status; // check current authstate if (pAccInfo == NULL) { return CAXMLErrorMessage::ERR_NO_RECORD_FOUND; } pAccInfo->mutex->lock(); if (pAccInfo->authFlags & AUTH_DELETE_ENTRY) { pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_NO_ERROR_GIVEN; } if( (!(pAccInfo->authFlags & AUTH_GOT_ACCOUNTCERT)) || (!(pAccInfo->authFlags & AUTH_CHALLENGE_SENT)) ) { pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_NO_ERROR_GIVEN; } pAccInfo->authFlags &= ~AUTH_CHALLENGE_SENT; // get raw bytes of response if ( getDOMElementValue( root, decodeBuffer, &decodeBufferLen ) != E_SUCCESS ) { CAMsg::printMsg( LOG_DEBUG, "ChallengeResponse has wrong XML format. Ignoring\n" ); pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_WRONG_FORMAT; } usedLen = decodeBufferLen; decodeBufferLen = 512; CABase64::decode( decodeBuffer, usedLen, decodeBuffer, &decodeBufferLen ); /* UINT8 b64Challenge[ 512 ]; UINT32 b64Len = 512; CABase64::encode(pHashEntry->pAccountingInfo->pChallenge, 222, b64Challenge, &b64Len); CAMsg::printMsg(LOG_DEBUG, "Challenge:\n%s\n", b64Challenge); */ // check signature //pDsaSig = DSA_SIG_new(); CASignature * sigTester = pAccInfo->pPublicKey; //sigTester->decodeRS( decodeBuffer, decodeBufferLen, pDsaSig ); if ( sigTester->verifyDER( pAccInfo->pChallenge, 222, decodeBuffer, decodeBufferLen ) != E_SUCCESS ) { UINT8 accountNrAsString[32]; print64(accountNrAsString, pAccInfo->accountNumber); CAMsg::printMsg(LOG_ERR, "Challenge-response authentication failed for account %s!\n", accountNrAsString); pAccInfo->authFlags |= AUTH_FAKE; pAccInfo->authFlags &= ~AUTH_ACCOUNT_OK; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_BAD_SIGNATURE; } // fetch cost confirmation from last session if available, and retrieve information; synchronized with settle thread bool bSettled; CAAccountingDBInterface *dbInterface = CAAccountingDBInterface::getConnection(); if(dbInterface != NULL) { dbInterface->getCostConfirmation(pAccInfo->accountNumber, m_currentCascade, &pCC, bSettled); } if (pCC != NULL) { if(!cascadeMatchesCC(pCC)) { delete pCC; pCC = NULL; CAMsg::printMsg(LOG_INFO, "CC do not match current Cascade. Discarding CC.\n"); } } if (pCC != NULL) { if (bSettled) { pAccInfo->authFlags &= ~AUTH_WAITING_FOR_FIRST_SETTLED_CC; } pAccInfo->transferredBytes += pCC->getTransferredBytes(); pAccInfo->confirmedBytes = pCC->getTransferredBytes(); #ifdef DEBUG UINT8 tmp[32]; print64(tmp,pAccInfo->transferredBytes); CAMsg::printMsg(LOG_DEBUG, "Setting confirmedBytes to %Lu\n", pAccInfo->confirmedBytes); CAMsg::printMsg(LOG_DEBUG, "pAccInfo->transferredBytes is now %s\n", tmp); #endif //delete pCC; } else { UINT8 tmp[32]; print64(tmp,pAccInfo->accountNumber); CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Cost confirmation for account %s not found in database. This seems to be a new user.\n", tmp); } /** @todo We need this trick so that the program does not freeze with active AI ThreadPool!!!! */ //pAccInfo->mutex->unlock(); m_currentAccountsHashtable->getMutex()->lock(); pAccInfo->authFlags |= AUTH_ACCOUNT_OK; // authentication successful loginEntry = (AccountLoginHashEntry*)m_currentAccountsHashtable->getValue(&(pAccInfo->accountNumber)); if (!loginEntry) { // remember that this user is logged in at least once loginEntry = new AccountLoginHashEntry; loginEntry->accountNumber = pAccInfo->accountNumber; loginEntry->count = 1; loginEntry->confirmedBytes = 0; loginEntry->authRemoveFlags = 0; loginEntry->authFlags = 0; loginEntry->userID = pAccInfo->userID; m_currentAccountsHashtable->put(&(loginEntry->accountNumber), loginEntry); if (!(AccountLoginHashEntry*)m_currentAccountsHashtable->getValue(&(pAccInfo->accountNumber))) { UINT8 accountNrAsString[32]; print64(accountNrAsString, pAccInfo->accountNumber); CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: Could not insert login entry for account %s!", accountNrAsString); } } else { loginEntry->count++; } if (loginEntry->count > 1) { /* * There already is a user logged in with this account. */ UINT8 accountNrAsString[32]; print64(accountNrAsString, pAccInfo->accountNumber); if (loginEntry->count < MAX_TOLERATED_MULTIPLE_LOGINS) { // There is now more than one user logged in with this account; kick out the other users! CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Multiple logins (%d) of user with account %s detected! \ Kicking out other users with this account...\n", loginEntry->count, accountNrAsString); loginEntry->userID = pAccInfo->userID; // this is the current user; kick out the others } else { /* The maximum of tolerated concurrent logins for this user is exceeded. * He won't get any new access again before the old connections have been closed! */ CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Maximum of multiple logins exceeded (%d) for user with account %s! \ Kicking out this user!\n", loginEntry->count, accountNrAsString); bSendCCRequest = false; // not needed... pAccInfo->authFlags |= AUTH_MULTIPLE_LOGIN; } } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Checking database for previously prepaid bytes...\n"); #endif //prepaidAmount = m_dbInterface->getPrepaidAmount(pAccInfo->accountNumber, m_currentCascade, true); if(dbInterface != NULL) { prepaidAmount = dbInterface->getPrepaidAmount(pAccInfo->accountNumber, m_currentCascade, true); } else { prepaidAmount = 0; } UINT8 tmp[32]; print64(tmp,pAccInfo->accountNumber); if (prepaidAmount > 0) { CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Got %d prepaid bytes for account nr. %s.\n",prepaidAmount, tmp); //pAccInfo->authFlags &= ~AUTH_WAITING_FOR_FIRST_SETTLED_CC; if (pAccInfo->transferredBytes >= (UINT32)prepaidAmount) { pAccInfo->transferredBytes -= prepaidAmount; } else { UINT8 tmp2[32]; print64(tmp2, pAccInfo->transferredBytes); CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: Transferred bytes of %s for account %s are lower than prepaid amount! " "Maybe we lost a CC?\n",tmp2, tmp); prepaidAmount = 0; } } else { CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: No database record for prepaid bytes found for account nr. %s.\n", tmp); } //CAMsg::printMsg(LOG_DEBUG, "Number of prepaid (confirmed-transferred) bytes : %d \n",pAccInfo->confirmedBytes-pAccInfo->transferredBytes); /** * @todo Dangerous, as this may collide with previous accounts that have been * used and deleted before... * There should be something like an expiration date for the account status, e.g. 1 month */ char expireBuf[10]; memset(expireBuf, 0, 10); SINT32 dbRet; if(dbInterface != NULL); { dbRet = dbInterface->getAccountStatus(pAccInfo->accountNumber, status, expireBuf); CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } if (dbRet != E_SUCCESS) { UINT8 tmp[32]; print64(tmp,pAccInfo->accountNumber); CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: Could not check status for account %s!\n", tmp); } else if (status > CAXMLErrorMessage::ERR_OK) { UINT32 authFlags = 0; UINT8 tmp[32]; SINT32 dateComp = -1; struct tm *expireDate = new struct tm; time_t nowTime = time(NULL); struct tm *now = localtime(&nowTime); char nowBuf[10]; print64(tmp,pAccInfo->accountNumber); if(expireBuf[0] != 0) { strptime((const char*)expireBuf,"%m/%d/%y", expireDate); dateComp= compDate(expireDate, now); } else { CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Warning no expiration date was given for account %s with illegal status %u\n", tmp, status); //@todo: delete this accountstatus. Right now we ignore this case. } /* strftime(nowBuf, 9, "%m/%d/%y", now); CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: account %s status %u expires on %s, today is %s\n", tmp, status, expireBuf, nowBuf); */ // Accountstatus is valid if(dateComp >= 0) { CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Illegal status %u for account %s is still valid, user is not allowed to login\n", status, tmp); if (status == CAXMLErrorMessage::ERR_BLOCKED) { authFlags |= AUTH_BLOCKED; pAccInfo->authFlags |= AUTH_BLOCKED; } else if (status == CAXMLErrorMessage::ERR_KEY_NOT_FOUND) { authFlags |= AUTH_INVALID_ACCOUNT; } else if (status == CAXMLErrorMessage::ERR_ACCOUNT_EMPTY) { authFlags |= AUTH_ACCOUNT_EMPTY; pAccInfo->authFlags |= AUTH_ACCOUNT_EMPTY; } delete expireDate; expireDate = NULL; CAMsg::printMsg(LOG_ERR, "CAAccountingInstance: The user with account %s should be kicked out due to error %u, expDate %s!\n", tmp, status, expireBuf); if (authFlags) { loginEntry->authFlags |= authFlags; if (loginEntry->confirmedBytes == 0) { loginEntry->confirmedBytes = pAccInfo->confirmedBytes; } } m_currentAccountsHashtable->getMutex()->unlock(); pAccInfo->mutex->unlock(); delete pCC; pCC = NULL; return status; } /*else { //@todo: perhaps forcing settlement }*/ delete expireDate; expireDate = NULL; } m_currentAccountsHashtable->getMutex()->unlock(); /** @todo We need this trick so that the program does not freeze with active AI ThreadPool!!!! */ //pAccInfo->mutex->lock(); #ifdef DEBUG CAMsg::printMsg(LOG_INFO, "HandleChallenge: TransferredBytes: %Lu ConfirmedBytes: %Lu\n", pAccInfo->transferredBytes, pAccInfo->confirmedBytes); #endif if (bSendCCRequest) { // fetch cost confirmation from last session if available, and send it //CAXMLCostConfirmation * pCC = NULL; //m_dbInterface->getCostConfirmation(pAccInfo->accountNumber, m_currentCascade, &pCC); if(pCC != NULL) { #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Sending pcc to sign with %Lu transferred bytes\n", pCC->getTransferredBytes()); #endif // the typical case; the user had logged in before /* there shouldn't be any counting synchronisation problems with the JAP * because the new login protocol doesn't permit JAPs * to exchange data before login is finished. */ UINT32 prepaidIval = pglobalOptions->getPrepaidInterval(); pAccInfo->bytesToConfirm = (prepaidIval - prepaidAmount) + pCC->getTransferredBytes(); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: bytesToConfirm: %Lu, prepaidIval: %u, prepaidAmount: %i, transferred bytes: %Lu\n", pAccInfo->bytesToConfirm, prepaidIval, prepaidAmount, pCC->getTransferredBytes()); #endif pAccInfo->pControlChannel->sendXMLMessage(pCC->getXMLDocument()); //delete pCC; } else { // there is no CC in the database; typically this is the first connection of this user if (prepaidAmount > 0) { // Delete any previously stored prepaid amount; there should not be any! CC lost? pAccInfo->transferredBytes += prepaidAmount; } sendCCRequest(pAccInfo); } } delete pCC; pCC = NULL; if ( pAccInfo->pChallenge != NULL ) // free mem { delete[] pAccInfo->pChallenge; pAccInfo->pChallenge = NULL; } //CAMsg::printMsg( LOG_ERR, "CAAccountingInstance::handleChallengeResponse stop\n"); pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_OK; } UINT32 CAAccountingInstance::handleCostConfirmation(tAiAccountingInfo* pAccInfo, DOMElement* root) { return handleCostConfirmation_internal(pAccInfo, root); INIT_STACK; FINISH_STACK("CAAccountingInstance::handleCostConfirmation"); } /** * Handles a cost confirmation sent by a jap */ UINT32 CAAccountingInstance::handleCostConfirmation_internal(tAiAccountingInfo* pAccInfo, DOMElement* root) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::handleCostConfirmation"); if (pAccInfo == NULL) { return CAXMLErrorMessage::ERR_NO_RECORD_FOUND; } pAccInfo->mutex->lock(); if (pAccInfo->authFlags & (AUTH_DELETE_ENTRY | AUTH_ACCOUNT_EMPTY)) { // ignore CCs for this account! pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_NO_ERROR_GIVEN; } // check authstate if (!(pAccInfo->authFlags & AUTH_GOT_ACCOUNTCERT) || !(pAccInfo->authFlags & AUTH_ACCOUNT_OK) || !(pAccInfo->authFlags & AUTH_SENT_CC_REQUEST)) { CAMsg::printMsg(LOG_ERR, "CAAccountingInstance::handleCostConfirmation CC was received but has not been requested! Ignoring...\n"); pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_NO_ERROR_GIVEN; } CAXMLCostConfirmation* pCC = CAXMLCostConfirmation::getInstance(root); if(pCC==NULL) { pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR; } // for debugging only: test signature the oldschool way // warning this removes the signature from doc!!! if (pAccInfo->pPublicKey==NULL|| pAccInfo->pPublicKey->verifyXML( root ) != E_SUCCESS) { // wrong signature CAMsg::printMsg( LOG_INFO, "CostConfirmation has INVALID SIGNATURE!\n" ); CAXMLErrorMessage err(CAXMLErrorMessage::ERR_BAD_SIGNATURE, (UINT8*)"CostConfirmation has bad signature"); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } delete pCC; pCC = NULL; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_BAD_SIGNATURE; } #ifdef DEBUG else { CAMsg::printMsg( LOG_DEBUG, "CostConfirmation Signature is OK.\n"); } #endif if (pCC->getNumberOfHashes() != m_allHashesLen) { CAMsg::printMsg( LOG_INFO, "CostConfirmation has illegal number of price cert hashes!\n" ); CAXMLErrorMessage err(CAXMLErrorMessage::ERR_BAD_REQUEST, (UINT8*)"CostConfirmation has illegal number of price cert hashes"); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } delete pCC; pCC = NULL; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_WRONG_FORMAT; } /*Hashtable* certHashCC = new Hashtable((UINT32 (*)(void *))Hashtable::stringHash, (SINT32 (*)(void *,void *))Hashtable::stringCompare); UINT8* certHash;*/ //bool bFailed = false; //for (UINT32 i = 0; i < pCC->getNumberOfHashes(); i++) //{ // certHash = pCC->getPriceCertHash(i); // certHashCC->put(certHash, certHash); /* if ((certHash = (UINT8*)certHashCC->getValue(certHash)) != NULL) { CAMsg::printMsg( LOG_INFO, "CC1: %s\n", certHash); }*/ //} //for (UINT32 i = 0; i < m_allHashesLen; i++) //{ //CAMsg::printMsg( LOG_INFO, "CA: %s\n", m_allHashes[i]); // certHash = (UINT8*)certHashCC->remove(m_allHashes[i]); // if (certHash == NULL) // { // bFailed = true; // break; // } // else // { // delete[] certHash; // } //} //certHashCC->clear(HASH_EMPTY_NONE, HASH_EMPTY_DELETE); //delete certHashCC; if (!cascadeMatchesCC(pCC)) { CAMsg::printMsg( LOG_INFO, "CostConfirmation has invalid price cert hashes!\n" ); CAXMLErrorMessage err(CAXMLErrorMessage::ERR_BAD_REQUEST, (UINT8*)"CostConfirmation has invalid price cert hashes"); XERCES_CPP_NAMESPACE::DOMDocument* errDoc=NULL; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc); if (errDoc != NULL) { errDoc->release(); errDoc = NULL; } delete pCC; pCC = NULL; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_WRONG_DATA; } // parse & set transferredBytes //when using Prepayment, this check is outdated, but left in to notice the most crude errors/cheats //The CC's transferredBytes should be equivalent to //AccInfo's confirmed bytes + the Config's PrepaidInterval - the number of bytes transferred between //requesting and receiving the CC #ifdef DEBUG CAMsg::printMsg( LOG_DEBUG, "received cost confirmation for %Lu transferred bytes where confirmed bytes are %Lu, we need %Lu bytes to confirm" ", mix already counted %Lu transferred bytes\n", pCC->getTransferredBytes(), pAccInfo->confirmedBytes, pAccInfo->bytesToConfirm, pAccInfo->transferredBytes); #endif if (pCC->getTransferredBytes() < pAccInfo->confirmedBytes) { CAMsg::printMsg( LOG_ERR, "CostConfirmation has insufficient number of bytes (%Lu < %Lu). kickout user...\n", pCC->getTransferredBytes(), pAccInfo->confirmedBytes ); //@todo: perhaps we should use another flag to indicate that this user should be kicked out. pAccInfo->authFlags |= AUTH_FAKE; delete pCC; pCC = NULL; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_WRONG_DATA; /* CAXMLErrorMessage err(CAXMLErrorMessage::ERR_WRONG_DATA, (UINT8*)"Your CostConfirmation has a wrong number of transferred bytes"); DOM_Document errDoc; err.toXmlDocument(errDoc); pAccInfo->pControlChannel->sendXMLMessage(errDoc);*/ } else { /* UINT8 tmp[32]; print64(tmp,pCC->getTransferredBytes()); CAMsg::printMsg( LOG_ERR, "Transferredbytes in CC: %s\n", tmp); */ SINT32 dbRet = E_UNKNOWN; CAAccountingDBInterface *dbInterface = CAAccountingDBInterface::getConnection(); if(dbInterface != NULL) { dbRet = dbInterface->storeCostConfirmation(*pCC, m_currentCascade); CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } if (dbRet != E_SUCCESS) { UINT8 tmp[32]; print64(tmp,pCC->getAccountNumber()); CAMsg::printMsg( LOG_INFO, "CostConfirmation for account %s could not be stored in database!\n", tmp ); pAccInfo->authFlags |= AUTH_DATABASE; } else { pAccInfo->confirmedBytes = pCC->getTransferredBytes(); if (pAccInfo->authFlags & AUTH_WAITING_FOR_FIRST_SETTLED_CC) { // initiate immediate settling #ifdef DEBUG UINT64 currentMillis; UINT8 tmpStrCurrentMillis[50]; getcurrentTimeMillis(currentMillis); print64(tmpStrCurrentMillis,currentMillis); CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread: Settle ini: %s\n", tmpStrCurrentMillis); #endif m_pSettleThread->settle(); } } } if (pAccInfo->confirmedBytes >= pAccInfo->bytesToConfirm) { // the user confirmed everything we wanted; if a timeout has been set, it should be reset pAccInfo->authFlags &= ~AUTH_HARD_LIMIT_REACHED; pAccInfo->lastHardLimitSeconds = time(NULL); } else { /*UINT8 tmp[32], tmp2[32], tmp3[32]; print64(tmp, pCC->getTransferredBytes()); print64(tmp2, pCC->getAccountNumber()); print64(tmp3, pAccInfo->bytesToConfirm);*/ CAMsg::printMsg(LOG_ERR, "AccountingSettleThread: Requested CC value has NOT been confirmed by account nr %Lu! " "Received Bytes: %Lu/%Lu " "Client should not be allowed to login.\n", pCC->getAccountNumber(), pCC->getTransferredBytes(), pAccInfo->bytesToConfirm); if(pAccInfo->authFlags & AUTH_LOGIN_SKIP_SETTLEMENT) { CAMsg::printMsg( LOG_INFO, "Skip settlement revoked.\n"); pAccInfo->authFlags &= ~AUTH_LOGIN_SKIP_SETTLEMENT; } /*delete pCC; pCC = NULL; pAccInfo->mutex->unlock(); pAccInfo->authFlags |= AUTH_FAKE; return CAXMLErrorMessage::ERR_WRONG_DATA;*/ //m_pSettleThread->settle(); } pAccInfo->bytesToConfirm = 0; pAccInfo->authFlags &= ~AUTH_SENT_CC_REQUEST; delete pCC; pCC = NULL; pAccInfo->mutex->unlock(); return CAXMLErrorMessage::ERR_OK; } /** * This must be called whenever a JAP is connecting to init our per-user * data structures */ SINT32 CAAccountingInstance::initTableEntry( fmHashTableEntry * pHashEntry ) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::initTableEntry"); //ms_pInstance->m_pMutex->lock(); if (pHashEntry == NULL) { FINISH_STACK("CAAccountingInstance::initTableEntry:NULL"); return E_UNKNOWN; } pHashEntry->pAccountingInfo = new tAiAccountingInfo; memset( pHashEntry->pAccountingInfo, 0, sizeof( tAiAccountingInfo ) ); SAVE_STACK("CAAccountingInstance::initTableEntry", "After memset"); pHashEntry->pAccountingInfo->authFlags = AUTH_SENT_ACCOUNT_REQUEST | AUTH_TIMEOUT_STARTED | AUTH_HARD_LIMIT_REACHED | AUTH_WAITING_FOR_FIRST_SETTLED_CC | AUTH_SENT_CC_REQUEST | AUTH_LOGIN_NOT_FINISHED; // prevents multiple CC requests on login pHashEntry->pAccountingInfo->authTimeoutStartSeconds = time(NULL); pHashEntry->pAccountingInfo->lastHardLimitSeconds = time(NULL); pHashEntry->pAccountingInfo->sessionPackets = 0; pHashEntry->pAccountingInfo->transferredBytes = 0; pHashEntry->pAccountingInfo->confirmedBytes = 0; pHashEntry->pAccountingInfo->bytesToConfirm = 0; pHashEntry->pAccountingInfo->nrInQueue = 0; pHashEntry->pAccountingInfo->userID = pHashEntry->id; pHashEntry->pAccountingInfo->mutex = new CAMutex; //ms_pInstance->m_pMutex->unlock(); FINISH_STACK("CAAccountingInstance::initTableEntry"); return E_SUCCESS; } /** * This should always be called when closing a JAP connection * to cleanup the payment data structures and store prepaid bytes */ SINT32 CAAccountingInstance::cleanupTableEntry( fmHashTableEntry *pHashEntry ) { INIT_STACK; BEGIN_STACK("CAAccountingInstance::cleanupTableEntry"); //ms_pInstance->m_pMutex->lock(); tAiAccountingInfo* pAccInfo = pHashEntry->pAccountingInfo; AccountLoginHashEntry* loginEntry; SINT32 prepaidBytes = 0; UINT32 prepaidInterval = pglobalOptions->getPrepaidInterval(); if (pAccInfo == NULL) { SAVE_STACK("CAAccountingInstance::cleanupTableEntry", "acc info null"); //ms_pInstance->m_pMutex->unlock(); return E_UNKNOWN; } pAccInfo->mutex->lock(); pHashEntry->pAccountingInfo=NULL; if (pAccInfo->accountNumber) { if (pAccInfo->authFlags & AUTH_ACCOUNT_OK) { // remove login ms_pInstance->m_currentAccountsHashtable->getMutex()->lock(); loginEntry = (AccountLoginHashEntry*)ms_pInstance->m_currentAccountsHashtable->getValue(&(pAccInfo->accountNumber)); if (loginEntry) { // test: delete CC!!! //ms_pInstance->m_dbInterface->deleteCC(pAccInfo->accountNumber, ms_pInstance->m_currentCascade); if (pAccInfo->userID == loginEntry->userID)// && //!(pAccInfo->authFlags & AUTH_WAITING_FOR_FIRST_SETTLED_CC)) { if (loginEntry->authFlags & AUTH_ACCOUNT_EMPTY) { // make sure to store the correct number of prepaid bytes pAccInfo->confirmedBytes = loginEntry->confirmedBytes; } //store prepaid bytes in database, so the user wont lose the prepaid amount by disconnecting prepaidBytes = getPrepaidBytes(pAccInfo); if (prepaidBytes > 0) { if (prepaidBytes > prepaidInterval) { UINT8 tmp[32]; print64(tmp, pAccInfo->accountNumber); /* Client paid more than the prepaid interval - * this is beyond specification and not allowed! */ CAMsg::printMsg(LOG_ERR, "PrepaidBytes of %d for account %s are higher than prepaid interval! " "The client did not behave according to specification. " "Deleting %d bytes...\n", prepaidBytes, tmp, prepaidBytes - prepaidInterval); prepaidBytes = prepaidInterval; } } /*if (ms_pInstance->m_dbInterface) { ms_pInstance->m_dbInterface->storePrepaidAmount(pAccInfo->accountNumber,prepaidBytes, ms_pInstance->m_currentCascade); }*/ CAAccountingDBInterface *dbInterface = CAAccountingDBInterface::getConnection(); if(dbInterface != NULL) { dbInterface->storePrepaidAmount(pAccInfo->accountNumber, prepaidBytes, ms_pInstance->m_currentCascade); CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } } if (loginEntry->count <= 1) { if (loginEntry->count < 1) { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: Cleanup found non-positive number of user login hash entries (%d)!\n", loginEntry->count); } // this is the last active user connection; delete the entry ms_pInstance->m_currentAccountsHashtable->remove(&(pAccInfo->accountNumber)); delete loginEntry; loginEntry = NULL; } else { // there are other connections from this user loginEntry->count--; } } else { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: Cleanup did not find user login hash entry!\n"); } ms_pInstance->m_currentAccountsHashtable->getMutex()->unlock(); } } else { CAMsg::printMsg(LOG_DEBUG, "CAAccountingInstance: Cleanup method found account zero.\n"); } //free memory of pAccInfo delete pAccInfo->pPublicKey; pAccInfo->pPublicKey = NULL; delete [] pAccInfo->pChallenge; pAccInfo->pChallenge = NULL; delete [] pAccInfo->pstrBIID; pAccInfo->pstrBIID = NULL; pHashEntry->pAccountingInfo=NULL; if (pAccInfo->nrInQueue > 0) { /* if (pAccInfo->accountNumber == 0) { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: AI queue entries found for account zero: %u!\n", pAccInfo->nrInQueue); } else if (!(pAccInfo->authFlags & AUTH_ACCOUNT_OK)) { UINT8 accountNrAsString[32]; print64(accountNrAsString, pAccInfo->accountNumber); CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: AI queue entries found for unauthorized account %s: %u!\n", accountNrAsString, pAccInfo->nrInQueue); } else*/ { // there are still entries in the ai queue; empty it before deletion; we cannot delete it now pAccInfo->authFlags |= AUTH_DELETE_ENTRY; } } else if (pAccInfo->nrInQueue < 0) { CAMsg::printMsg(LOG_CRIT, "CAAccountingInstance: Cleanup method found negative handle queue!\n"); } pAccInfo->mutex->unlock(); if (!(pAccInfo->authFlags & AUTH_DELETE_ENTRY)) { // there are no handles for this entry in the queue, we can savely delete it now delete pAccInfo->mutex; pAccInfo->mutex = NULL; delete pAccInfo; pAccInfo = NULL; } else { CAMsg::printMsg(LOG_INFO, "CAAccountingInstance: Cleanup method sent account deletion request to AI thread!\n"); } //ms_pInstance->m_pMutex->unlock(); FINISH_STACK("CAAccountingInstance::cleanupTableEntry"); return E_SUCCESS; } /* Settlement transaction prcodure as it is called by the SettleThread * NEVER INVOKE THIS METHOD IF YOU'RE HOLDING A LOCK ON m_currentAccountsHashtable !! * */ SINT32 CAAccountingInstance::settlementTransaction() { INIT_STACK; BEGIN_STACK("CAAccountingInstance::settlementTransaction"); SINT32 ret = 0; CAXMLErrorMessage * pErrMsg = NULL; CAXMLCostConfirmation * pCC = NULL; CAQueue q; UINT32 size, qSize, nrOfCCs; SettleEntry *entry = NULL, *nextEntry = NULL; bool bDeleteCC = false; UINT32 authFlags = 0; UINT32 authRemoveFlags = 0; UINT64 confirmedBytes = 0; UINT64 diffBytes = 0; CAAccountingDBInterface *dbInterface = NULL; /* This should never happen */ if(ms_pInstance == NULL) { FINISH_STACK("CAAccountingInstance::settlementTransaction"); return E_UNKNOWN; } /* This should never happen */ if(ms_pInstance->m_pSettlementMutex == NULL) { FINISH_STACK("CAAccountingInstance::settlementTransaction"); return E_UNKNOWN; } //sleep(5); dbInterface = CAAccountingDBInterface::getConnection(); if(dbInterface == NULL) { CAMsg::printMsg(LOG_ERR, "Settlement transaction: could not connect to Database. Retry later...\n"); //MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionFailure); FINISH_STACK("CAAccountingInstance::settlementTransaction"); return E_NOT_CONNECTED; } //MONITORING_FIRE_PAY_EVENT(ev_pay_dbConnectionSuccess); ms_pInstance->m_pSettlementMutex->lock(); /* First part get unsettled CCs from the AI database */ #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: DB connections established!\n"); #endif dbInterface->getUnsettledCostConfirmations(q, ms_pInstance->m_currentCascade); if (q.isEmpty()) { CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: finished gettings CCs, found no CCs to settle\n"); if(dbInterface != NULL) { CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } ms_pInstance->m_pSettlementMutex->unlock(); FINISH_STACK("CAAccountingInstance::settlementTransaction"); return E_SUCCESS; } qSize = q.getSize(); nrOfCCs = qSize / sizeof(pCC); CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: finished gettings CCs, found %u cost confirmations to settle\n",nrOfCCs); SAVE_STACK("CAAccountingInstance::settlementTransaction", "After getting unsettled CCs"); /* Second part: We found unsettled CCs. Now contact the Payment Instance to settle them */ while(!q.isEmpty()) { // get the next CC from the queue size = sizeof(pCC); ret = q.get((UINT8*)(&pCC), &size); if(ret != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "Settlement transaction: could not get next item from queue\n"); q.clean(); if(dbInterface != NULL) { CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; } ms_pInstance->m_pSettlementMutex->unlock(); FINISH_STACK("CAAccountingInstance::settlementTransaction"); return ret; //break; } if (!pCC) { CAMsg::printMsg(LOG_CRIT, "Settlement transaction: Cost confirmation is NULL!\n"); continue; } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: Connecting to payment instance...\n"); #endif ret = ms_pInstance->m_pPiInterface->initBIConnection(); if(ret != E_SUCCESS) { ms_pInstance->m_seqBIConnErrors++; if(ms_pInstance->m_seqBIConnErrors >= CRITICAL_SUBSEQUENT_BI_CONN_ERRORS) { //transition to critical BI conn payment state MONITORING_FIRE_PAY_EVENT(ev_pay_biConnectionCriticalSubseqFailures); } else { MONITORING_FIRE_PAY_EVENT(ev_pay_biConnectionFailure); } CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: could not connect to BI. Try later...\n"); //q.clean(); pErrMsg = NULL; // continue in order to tell AUTH_WAITING_FOR_FIRST_SETTLED_CC for all accounts ms_pInstance->m_pPiInterface->terminateBIConnection(); // make sure the socket is closed } else { MONITORING_FIRE_PAY_EVENT(ev_pay_biConnectionSuccess); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: successfully connected to payment instance"); #endif ms_pInstance->m_seqBIConnErrors = 0; pErrMsg = ms_pInstance->m_pPiInterface->settle( *pCC ); ms_pInstance->m_pPiInterface->terminateBIConnection(); CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: settle done!\n"); } // check returncode if(pErrMsg == NULL) //no returncode -> connection error { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; // no fault of the client CAMsg::printMsg(LOG_ERR, "Settlement transaction: Communication with BI failed!\n"); } else if(pErrMsg->getErrorCode() != pErrMsg->ERR_OK) //BI reported error { CAMsg::printMsg(LOG_ERR, "Settlement transaction: BI reported error no. %d (%s)\n", pErrMsg->getErrorCode(), pErrMsg->getDescription() ); if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_KEY_NOT_FOUND) { authFlags |= AUTH_INVALID_ACCOUNT; //dbConn.storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_KEY_NOT_FOUND); bDeleteCC = true; } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_ACCOUNT_EMPTY) { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; authFlags |= AUTH_ACCOUNT_EMPTY; UINT64* msgConfirmedBytes = (UINT64*)pErrMsg->getMessageObject(); if (msgConfirmedBytes) { confirmedBytes = *msgConfirmedBytes; if (confirmedBytes < pCC->getTransferredBytes()) { diffBytes = pCC->getTransferredBytes() - confirmedBytes; } UINT8 tmp[32]; print64(tmp, confirmedBytes); CAMsg::printMsg(LOG_INFO, "Settlement transaction: Received %s confirmed bytes!\n", tmp); } else { CAMsg::printMsg(LOG_ERR, "Settlement transaction: Account empty, but no message object received! " "This may lead to too much prepaid bytes!\n"); } //check if expDate is set don't store status otherwise /*if(pErrMsg->getExpTimeString()!=NULL) { if(*(pErrMsg->getExpTimeString())!=0) { dbInterface->storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_ACCOUNT_EMPTY, pErrMsg->getExpTimeString()); } }*/ dbInterface->storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_ACCOUNT_EMPTY, pErrMsg->getExpTimeString()); dbInterface->markAsSettled(pCC->getAccountNumber(), ms_pInstance->m_currentCascade, pCC->getTransferredBytes()); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: settling %Lu bytes for account %Lu\n", pCC->getTransferredBytes(), pCC->getAccountNumber()); #endif } /* else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_INVALID_PRICE_CERT) { // this should never happen; the price certs in this CC do not fit to the ones of the cascade // bDeleteCC = true; }*/ else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_OUTDATED_CC) { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; // this is a Mix not a client error //get attached CC from error message CAXMLCostConfirmation* attachedCC = (CAXMLCostConfirmation*) pErrMsg->getMessageObject(); if (attachedCC) { authFlags |= AUTH_OUTDATED_CC; CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: tried outdated CC, received last valid CC back\n"); //store it in DB if (dbInterface->storeCostConfirmation(*attachedCC, ms_pInstance->m_currentCascade) == E_SUCCESS) { if (dbInterface->markAsSettled(attachedCC->getAccountNumber(), ms_pInstance->m_currentCascade, attachedCC->getTransferredBytes()) != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "Settlement transaction: Could not mark last valid CC as settled." "Maybe a new CC has been added meanwhile?\n"); } } else { CAMsg::printMsg(LOG_ERR, "Settlement transaction: storing last valid CC in db failed!\n"); } // set the confirmed bytes to the value of the CC got from the PI confirmedBytes = attachedCC->getTransferredBytes(); } else { CAMsg::printMsg(LOG_INFO, "Settlement transaction: Did not receive last valid CC - maybe old Payment instance?\n"); } } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_BLOCKED) { authFlags |= AUTH_BLOCKED; bDeleteCC = true; dbInterface->storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_BLOCKED, pErrMsg->getExpTimeString()); /* Don't forget to store the status when account is blocked but first check if expDate is set, otherwise don't store status */ /*if(pErrMsg->getExpTimeString()!=NULL) { if(*(pErrMsg->getExpTimeString())!=0) { dbInterface->storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_BLOCKED, pErrMsg->getExpTimeString()); } }*/ } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_DATABASE_ERROR) { //authFlags |= AUTH_DATABASE; // the user is not responsible for this! authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR || pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_SUCCESS_BUT_WITH_ERRORS) { // kick out the user and store the CC authFlags |= AUTH_UNKNOWN; } else { // an unknown error leads to user kickout CAMsg::printMsg(LOG_DEBUG, "Settlement transaction: Setting unknown kickout error no. %d.\n", pErrMsg->getErrorCode()); authFlags |= AUTH_UNKNOWN; bDeleteCC = true; } if (bDeleteCC) { //delete costconfirmation to avoid trying to settle an unusable CC again and again if(dbInterface->deleteCC(pCC->getAccountNumber(), ms_pInstance->m_currentCascade) == E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "Settlement transaction: unusable cost confirmation was deleted\n"); } else { CAMsg::printMsg(LOG_ERR, "Settlement transaction: cost confirmation is unusable, but could not delete it from database\n"); } } } else //settling was OK, so mark account as settled { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; if (dbInterface->markAsSettled(pCC->getAccountNumber(), ms_pInstance->m_currentCascade, pCC->getTransferredBytes()) != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "Settlement transaction: Could not mark CC as settled. Maybe a new CC has been added meanwhile?\n"); } CAMsg::printMsg(LOG_INFO, "Settlement transaction: CC OK!\n"); } if (authFlags || authRemoveFlags) { nextEntry = new SettleEntry; nextEntry->accountNumber = pCC->getAccountNumber(); nextEntry->authFlags = authFlags; nextEntry->authRemoveFlags = authRemoveFlags; nextEntry->confirmedBytes = confirmedBytes; nextEntry->diffBytes = diffBytes; nextEntry->nextEntry = entry; entry = nextEntry; } if (pCC != NULL) { delete pCC; pCC = NULL; } if (pErrMsg != NULL) { delete pErrMsg; pErrMsg = NULL; } } SAVE_STACK("CAAccountingInstance::settlementTransaction", "After settling unsettled CCs with BI"); SettleEntry *first = entry; UINT64 myWaitNr = 0; if (entry) { if(ms_pInstance->m_nextSettleNr == ms_pInstance->m_settleWaitNr) { //no one is waiting, we use this occasion to rest the wait numbers ms_pInstance->m_nextSettleNr = 0; ms_pInstance->m_settleWaitNr = 0; } else { SAVE_STACK("CAAccountingInstance::settlementTransaction", "wait for altering hashtable"); //get global wait number and wait but release the DBConnection first. CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; ms_pInstance->m_settleWaitNr++; myWaitNr = ms_pInstance->m_settleWaitNr; while(myWaitNr != ms_pInstance->m_nextSettleNr) { CAMsg::printMsg(LOG_INFO, "Thread must wait to alter login table after settling: %Lu before him in the queue\n", (myWaitNr - ms_pInstance->m_nextSettleNr)); ms_pInstance->m_pSettlementMutex->wait(); } dbInterface = CAAccountingDBInterface::getConnection(); } SAVE_STACK("CAAccountingInstance::settlementTransaction", "altering DB entries"); while (entry != NULL && dbInterface != NULL) { if (entry->authFlags & (AUTH_INVALID_ACCOUNT | AUTH_UNKNOWN)) { dbInterface->storePrepaidAmount( entry->accountNumber, 0, ms_pInstance->m_currentCascade); } else if (entry->diffBytes) { // user is currently not logged in; set correct prepaid bytes in DB SINT32 prepaidBytes = dbInterface->getPrepaidAmount(entry->accountNumber, ms_pInstance->m_currentCascade, true); if (prepaidBytes > 0) { if (entry->diffBytes >= (UINT32)prepaidBytes) { prepaidBytes = 0; } else { prepaidBytes -= entry->diffBytes; } dbInterface->storePrepaidAmount( entry->accountNumber, prepaidBytes, ms_pInstance->m_currentCascade); } } nextEntry = entry->nextEntry; entry = nextEntry; } } CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; ms_pInstance->m_pSettlementMutex->unlock(); if(first != NULL) { SAVE_STACK("CAAccountingInstance::settlementTransaction", "altering hashtable"); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Settlement thread with wait nr %Lu alters hashtable.\n", myWaitNr); #endif entry = first; ms_pInstance->m_currentAccountsHashtable->getMutex()->lock(); while (entry != NULL) { AccountLoginHashEntry* loginEntry = (AccountLoginHashEntry*) (ms_pInstance->m_currentAccountsHashtable->getValue(&(entry->accountNumber))); if (loginEntry) { // the user is currently logged in loginEntry->authFlags |= entry->authFlags; loginEntry->authRemoveFlags |= entry->authRemoveFlags; if (entry->confirmedBytes > 0 && loginEntry->confirmedBytes < entry->confirmedBytes) { loginEntry->confirmedBytes = entry->confirmedBytes; } } nextEntry = entry->nextEntry; delete entry; entry = nextEntry; } ms_pInstance->m_currentAccountsHashtable->getMutex()->unlock(); // In this case we get the next waiting thread to alter the table running ms_pInstance->m_pSettlementMutex->lock(); if(ms_pInstance->m_settleWaitNr != ms_pInstance->m_nextSettleNr) { SAVE_STACK("CAAccountingInstance::settlementTransaction", "waking up waiting threads for altering hashtable"); //There are Threads waiting CAMsg::printMsg(LOG_INFO, "Waking up next Thread %Lu are waiting.\n", (ms_pInstance->m_settleWaitNr - ms_pInstance->m_nextSettleNr)); ms_pInstance->m_nextSettleNr++; ms_pInstance->m_pSettlementMutex->broadcast(); } ms_pInstance->m_pSettlementMutex->unlock(); } /*if(dbInterface != NULL) { CAAccountingDBInterface::releaseConnection(dbInterface); dbInterface = NULL; }*/ FINISH_STACK("CAAccountingInstance::settlementTransaction"); return E_SUCCESS; } #endif /* ifdef PAYMENT */ anon-proxy-00.05.38+20081230/mix.spec0000644000175000017500000000354210571023405015366 0ustar daviddavid# norootforbuild Summary: Mix Server of the AN.ON project Name: Mix Version: 00.05.39 Release: 1 URL: http//anon.inf.tu-dresden.de/ Source0: mix.src.tgz License: BSD Group: Networking BuildRoot: %{_tmppath}/%{name}-root %if 0%{?suse_version} BuildRequires: gcc gzip gcc-c++ binutils glibc-devel openssl-devel Xerces-c-devel Xerces-c libstdc++-devel libstdc++ make %else BuildRequires: gcc gzip gcc-c++ binutils glibc-devel openssl-devel libstdc++-devel libstdc++ make xerces-c-doc-2.7.0 %endif %description This is the Mix server, which is part of the AN.ON project %prep %setup -q -n proxytest %build %{configure} make DESTDIR=${RPM_BUILD_ROOT} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=${RPM_BUILD_ROOT} install -d ${RPM_BUILD_ROOT}/etc/mix install -d ${RPM_BUILD_ROOT}/etc/init.d/rc2.d install -d ${RPM_BUILD_ROOT}/etc/init.d/rc3.d install -d ${RPM_BUILD_ROOT}/etc/init.d/rc5.d install -m u+rx -D documentation/init.d/mix ${RPM_BUILD_ROOT}/etc/init.d/mix ln -s ../mix ${RPM_BUILD_ROOT}/etc/init.d/rc2.d/S70mix ln -s ../mix ${RPM_BUILD_ROOT}/etc/init.d/rc3.d/S70mix ln -s ../mix ${RPM_BUILD_ROOT}/etc/init.d/rc5.d/S70mix %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) /usr/sbin/mix /etc/mix /etc/init.d/mix /etc/init.d/rc2.d/S70mix /etc/init.d/rc3.d/S70mix /etc/init.d/rc5.d/S70mix %changelog <<<<<<< mix.spec * Tue Feb 20 2007 JAP-Team - Updated to the new upstream Version 00.05.39 - Bug Fixes in configure scripts * Tue Jun 28 2005 JAP-Team - Fixed a Bug in the First Mix * Tue Jun 7 2005 JAP-Team - Initial build ======= *Tue Feb 20 2007 JAP-Team -Updated to the new upstream Version 00.05.39 *Tue Jun 28 2005 JAP-Team -Fixed a Bug in the First Mix *Tue Jun 7 2005 JAP-Team -Initial build >>>>>>> 1.9 anon-proxy-00.05.38+20081230/CASocket.cpp0000644000175000017500000005341511126465761016075 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #include "CASocket.hpp" #include "CAUtil.hpp" #include "CASocketAddrINet.hpp" #ifdef HAVE_UNIX_DOMAIN_PROTOCOL #include "CASocketAddrUnix.hpp" #endif #include "CASingleSocketGroup.hpp" #ifdef _DEBUG int sockets; #endif #include "CAMsg.hpp" #include "CAUtil.hpp" #define CLOSE_SEND 0x01 #define CLOSE_RECEIVE 0x02 #define CLOSE_BOTH 0x03 UINT32 CASocket::m_u32NormalSocketsOpen=0; //how many "normal" sockets are open UINT32 CASocket::m_u32MaxNormalSockets=0xFFFFFFFF; //how many "normal" sockets are allowed at max CASocket::CASocket(bool bIsReservedSocket) { m_Socket=0; m_bSocketIsClosed=true; m_bIsReservedSocket=bIsReservedSocket; } SINT32 CASocket::create() { return create(AF_INET, true); } SINT32 CASocket::create(int type) { return create(type, true); } SINT32 CASocket::create(bool a_bShowTypicalError) { return create(AF_INET, a_bShowTypicalError); } ///@todo Not thread safe! SINT32 CASocket::create(int type, bool a_bShowTypicalError) { if(m_bSocketIsClosed) { if(m_bIsReservedSocket||m_u32NormalSocketsOpen=m_u32MaxNormalSockets) { CAMsg::printMsg(LOG_CRIT,"CASocket::accept() -- Could not create a new normal Socket -- allowed number of normal sockets exeded!\n"); return E_SOCKET_LIMIT; } s.m_Socket=::accept(m_Socket,NULL,NULL); if(s.m_Socket==SOCKET_ERROR) { s.m_Socket=0; if(GET_NET_ERROR==ERR_INTERN_SOCKET_CLOSED) return E_SOCKETCLOSED; return E_UNKNOWN; } s.m_csClose.lock(); m_u32NormalSocketsOpen++; s.m_bSocketIsClosed=false; s.m_csClose.unlock(); return E_SUCCESS; } /** Tries to connect to the peer described by psa. * @param psa - peer * @param retry - number of retries * @param time - time between retries in seconds */ SINT32 CASocket::connect(const CASocketAddr & psa,UINT32 retry,UINT32 time) { // CAMsg::printMsg(LOG_DEBUG,"Socket:connect\n"); if(m_bSocketIsClosed&&create()!=E_SUCCESS) { return E_UNKNOWN; } #ifdef _DEBUG sockets++; #endif int err=0; const SOCKADDR* addr=psa.LPSOCKADDR(); int addr_len=psa.getSize(); for(UINT32 i=0;i0&&(UINT32)aktTimeOut==msTimeOut) //we already have the right timeout { ret=send(buff,len); } else if(aktTimeOut<0||setSendTimeOut(msTimeOut)!=E_SUCCESS) {//do it complicate but still to simple!!!! more work TODO setNonBlocking(true); ret=send(buff,len); if(ret==E_AGAIN) { CAMsg::printMsg(LOG_DEBUG,"Send again...\n"); msSleep((UINT16)msTimeOut); ret=send(buff,len); } setNonBlocking(bWasNonBlocking); } else { ret=send(buff,len); setSendTimeOut(aktTimeOut); } } return ret; } /** Sends all data over the network. This may block until all data is send. @param buff - the buffer of data to send @param len - content length @retval E_UNKNOWN, if an error occured @retval E_TIMEDOUT if the timeout was reached @retval E_SUCCESS, if successful */ SINT32 CASocket::sendFullyTimeOut(const UINT8* buff,UINT32 len, UINT32 msTimeOut, UINT32 msTimeOutSingleSend) { if(len==0) { return E_SUCCESS; //nothing to send } SINT32 ret; SINT32 aktTimeOut=0; UINT64 startupTime, currentMillis; bool bWasNonBlocking; getNonBlocking(&bWasNonBlocking); aktTimeOut=getSendTimeOut(); getcurrentTimeMillis(startupTime); if(bWasNonBlocking) { //we are in non-blocking mode return sendFully(buff, len); } else if (setSendTimeOut(msTimeOutSingleSend)!=E_SUCCESS) { // it is not possible to set the socket timeout CAMsg::printMsg(LOG_ERR,"CASocket::sendFullyTimeOut() - could not set socket timeout!\n"); return sendFully(buff, len); } else { for(;;) { getcurrentTimeMillis(currentMillis); if (currentMillis >= (startupTime + msTimeOut)) { #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG,"CASocket::sendFullyTimeOut() - timed out!\n"); #endif setSendTimeOut(aktTimeOut); return E_TIMEDOUT; } ret=send(buff,len); if((UINT32)ret==len) { setSendTimeOut(aktTimeOut); return E_SUCCESS; } else if(ret==E_AGAIN) { ret=CASingleSocketGroup::select_once(*this,true,1000); if(ret>=0||ret==E_TIMEDOUT) continue; #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"CASocket::sendTimeOutFully() - error near select_once() ret=%i\n",ret); #endif setSendTimeOut(aktTimeOut); return E_UNKNOWN; } else if(ret<0) { #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"CASocket::sendTimeOutFully() - send returned %i\n",ret); #endif setSendTimeOut(aktTimeOut); return E_UNKNOWN; } len-=ret; buff+=ret; } //could never be here.... } } /** Sends all data over the network. This may block until all data is send. @param buff - the buffer of data to send @param len - content length @retval E_UNKNOWN, if an error occured @retval E_SUCCESS, if successful */ SINT32 CASocket::sendFully(const UINT8* buff,UINT32 len) { if(len==0) return E_SUCCESS; //nothing to send SINT32 ret; for(;;) { ret=send(buff,len); if((UINT32)ret==len) return E_SUCCESS; else if(ret==E_AGAIN) { ret=CASingleSocketGroup::select_once(*this,true,1000); if(ret>=0||ret==E_TIMEDOUT) continue; #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"CASocket::sendFully() - error near select_once() ret=%i\n",ret); #endif return E_UNKNOWN; } else if(ret<0) { #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"CASocket::sendFully() - send returned %i\n",ret); #endif return E_UNKNOWN; } len-=ret; buff+=ret; } //could never be here.... } /** Will receive some bytes from the socket. May block or not depending on whatever this socket * was set to blocking or non-blocking mode. * Warning: If socket is in blocking mode and receive is called, receive will block until some * data is available, EVEN IF AN OTHER THREAD WILL CLOSE THIS SOCKET! * * @param buff the buffer which get the received data * @param len size of buff * @return SOCKET_ERROR if an error occured * @retval E_AGAIN, if socket was in non-blocking mode and * receive would block or a timeout was reached * @retval 0 if socket was gracefully closed * @return the number of bytes received (always >0) ***/ SINT32 CASocket::receive(UINT8* buff,UINT32 len) { int ret; int ef=0; do { ret=::recv(m_Socket,(char*)buff,len,MSG_NOSIGNAL); } while(ret==SOCKET_ERROR&&(ef=GET_NET_ERROR)==EINTR); if(ret==SOCKET_ERROR) { if(ef==ERR_INTERN_WOULDBLOCK) return E_AGAIN; } #ifdef _DEBUG if(ret==SOCKET_ERROR) CAMsg::printMsg(LOG_DEBUG,"CASocket Receive error %d (%s)\n",ef,GET_NET_ERROR_STR(ef)); #endif return ret; } /** Trys to receive all bytes. If after the timeout value has elapsed, * not all bytes are received * the error E_TIMEDOUT is returned. * @param buff byte array, where the received bytes would be stored * @param len on input holds the number of bytes which should be read, * @param msTimeOut the timout in milli seconds * @retval E_TIMEDOUT if not all byts could be read * @retval E_UNKNOWN if an error occured * @retval E_SUCCESS if all bytes could be read * */ SINT32 CASocket::receiveFullyT(UINT8* buff,UINT32 len,UINT32 msTimeOut) { SINT32 ret; UINT32 pos=0; UINT64 currentTime,endTime; getcurrentTimeMillis(currentTime); set64(endTime,currentTime); add64(endTime,msTimeOut); CASingleSocketGroup oSG(false); oSG.add(*this); for(;;) { ret=oSG.select(msTimeOut); if(ret==1) { ret=receive(buff+pos,len); if(ret<=0) return E_UNKNOWN; pos+=ret; len-=ret; } else if(ret==E_TIMEDOUT) return E_TIMEDOUT; if(len==0) return E_SUCCESS; getcurrentTimeMillis(currentTime); if(!isLesser64(currentTime,endTime)) return E_TIMEDOUT; msTimeOut=diff64(endTime,currentTime); } } SINT32 CASocket::receiveLine(UINT8* line, UINT32 maxLen, UINT32 msTimeOut) { UINT32 i = 0; UINT8 byte = 0; SINT32 ret = 0; UINT64 currentTime, endTime; getcurrentTimeMillis(currentTime); set64(endTime,currentTime); add64(endTime,msTimeOut); CASingleSocketGroup oSG(false); oSG.add(*this); do { ret = oSG.select(msTimeOut); if(ret == 1) { ret = receive(&byte, 1); if(byte == '\r' || byte == '\n') { line[i++] = 0; } else { line[i++] = byte; } } else if(ret == E_TIMEDOUT) { return E_TIMEDOUT; } getcurrentTimeMillis(currentTime); if(!isLesser64(currentTime,endTime)) { return E_TIMEDOUT; } msTimeOut=diff64(endTime,currentTime); } while(byte != '\n' && i 0); return ret; } /** * LERNGRUPPE * Returns the source address of the socket * @return r_Ip the source IP address * @retval E_SUCCESS upon success * @retval SOCKET_ERROR otherwise * * @todo: Question: Correct for Unix domain sockets? */ SINT32 CASocket::getLocalIP(UINT8 r_Ip[4]) { struct sockaddr_in addr; socklen_t namelen=sizeof(struct sockaddr_in); if(getsockname(m_Socket,(struct sockaddr*)&addr,&namelen)==SOCKET_ERROR) return SOCKET_ERROR; memcpy(r_Ip,&addr.sin_addr,4); return E_SUCCESS; } SINT32 CASocket::getLocalPort() { struct sockaddr_in addr; socklen_t namelen=sizeof(struct sockaddr_in); if(getsockname(m_Socket,(struct sockaddr*)&addr,&namelen)==SOCKET_ERROR) return SOCKET_ERROR; return ntohs(addr.sin_port); } SINT32 CASocket::getPeerIP(UINT8 ip[4]) { struct sockaddr_in addr; socklen_t namelen=sizeof(struct sockaddr_in); if(getpeername(m_Socket,(struct sockaddr*)&addr,&namelen)==SOCKET_ERROR) return SOCKET_ERROR; memcpy(ip,&addr.sin_addr,4); return E_SUCCESS; } SINT32 CASocket::getPeerPort() { struct sockaddr_in addr; socklen_t namelen=sizeof(struct sockaddr_in); if(getpeername(m_Socket,(struct sockaddr*)&addr,&namelen)==SOCKET_ERROR) return SOCKET_ERROR; return ntohs(addr.sin_port); } SINT32 CASocket::setReuseAddr(bool b) { int val=0; if(b) val=1; return setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(char*)&val,sizeof(val)); } SINT32 CASocket::setRecvBuff(UINT32 r) { int val=r; return setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(char*)&val,sizeof(val)); } SINT32 CASocket::getRecvBuff() { int val; socklen_t size=sizeof(val); if(getsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(char*)&val,&size)==SOCKET_ERROR) return E_UNKNOWN; else return val; } /** Returns < 0 on error, otherwise the new sendbuffersize (which may be less than r)*/ SINT32 CASocket::setSendBuff(SINT32 r) { if(r<0) return E_UNKNOWN; SINT32 val=r; SINT32 ret=setsockopt(m_Socket,SOL_SOCKET,SO_SNDBUF,(char*)&val,sizeof(val)); if(ret!=0) return E_UNKNOWN; return getSendBuff(); } SINT32 CASocket::getSendBuff() { SINT32 val; socklen_t size=sizeof(val); if(getsockopt(m_Socket,SOL_SOCKET,SO_SNDBUF,(char*)&val,&size)==SOCKET_ERROR) return E_UNKNOWN; else return val; } SINT32 CASocket::setSendTimeOut(UINT32 msTimeOut) { timeval t; t.tv_sec=msTimeOut/1000; t.tv_usec=(msTimeOut%1000)*1000; return setsockopt(m_Socket,SOL_SOCKET,SO_SNDTIMEO,(char*)&t,sizeof(t)); } SINT32 CASocket::getSendTimeOut() { timeval val; socklen_t size=sizeof(val); if(getsockopt(m_Socket,SOL_SOCKET,SO_SNDTIMEO,(char*)&val,&size)==SOCKET_ERROR) return E_UNKNOWN; else return val.tv_sec*1000+val.tv_usec/1000; } /** Enables/disables the socket keep-alive option. @param b true if option should be enabled, false otherwise @return E_SUCCESS if no error occured @return E_UNKOWN otherwise */ SINT32 CASocket::setKeepAlive(bool b) { int val=0; if(b) val=1; if(setsockopt(m_Socket,SOL_SOCKET,SO_KEEPALIVE,(char*)&val,sizeof(val))==SOCKET_ERROR) { int errnum = errno; CAMsg::printMsg(LOG_ERR, "Could not set KEEP_ALIVE options, cause: %s\n", strerror(errnum)); return E_UNKNOWN; } return E_SUCCESS; } /** Enables the socket keep-alive option with a given ping time (in seconds). @param sec the time intervall(in seconds) of a keep-alive message @return E_SUCCESS if no error occured @return E_UNKOWN otherwise */ SINT32 CASocket::setKeepAlive(UINT32 sec) { if(setKeepAlive(true)!=E_SUCCESS) { return E_UNKNOWN; } #ifdef HAVE_TCP_KEEPALIVE int val=sec; if(setsockopt(m_Socket,IPPROTO_TCP,TCP_KEEPALIVE,(char*)&val,sizeof(val))==SOCKET_ERROR) { return E_UNKNOWN; } return E_SUCCESS; #else return E_UNKNOWN; #endif } SINT32 CASocket::setNonBlocking(bool b) { if(b) { #ifndef _WIN32 int flags=fcntl(m_Socket,F_GETFL,0); fcntl(m_Socket,F_SETFL,flags|O_NONBLOCK); #else unsigned long flags=1; ioctlsocket(m_Socket,FIONBIO,&flags); #endif } else { #ifndef _WIN32 int flags=fcntl(m_Socket,F_GETFL,0); fcntl(m_Socket,F_SETFL,flags&~O_NONBLOCK); #else unsigned long flags=0; ioctlsocket(m_Socket,FIONBIO,&flags); #endif } return E_SUCCESS; } SINT32 CASocket::getNonBlocking(bool* b) { #ifndef _WIN32 int flags=fcntl(m_Socket,F_GETFL,0); *b=((flags&O_NONBLOCK)==O_NONBLOCK); return E_SUCCESS; #else return SOCKET_ERROR; #endif } SINT32 CASocket::getMaxOpenSockets() { CASocket* parSocket=new CASocket[10001]; UINT32 maxSocket=0; for(UINT32 t=0;t<10001;t++) { if(parSocket[t].create(false)!=E_SUCCESS) { maxSocket=t; break; } } for(UINT32 t=0;t0) ***/ virtual SINT32 receive(UINT8* buff,UINT32 len)=0; /** Receives all len bytes. This blocks until all bytes are received or an error occured. * @return E_UNKNOWN, in case of an error * @return E_SUCCESS otherwise ***/ SINT32 receiveFully(UINT8* buff,UINT32 len) { SINT32 ret; UINT32 pos=0; do { ret=receive(buff+pos,len); if(ret<=0) { if(ret==E_AGAIN) { msSleep(100); continue; } else { return E_UNKNOWN; } } pos+=ret; len-=ret; } while(len>0); return E_SUCCESS; } }; #endif anon-proxy-00.05.38+20081230/CALocalProxy.hpp0000644000175000017500000000464110466075044016740 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CALOCALPROXY__ #define __CALOCALPROXY__ #include "CAMix.hpp" #include "CAMuxSocket.hpp" #include "CAASymCipher.hpp" // How many packets do you want to replay at a time? #define REPLAY_COUNT 16 #ifndef NEW_MIX_TYPE class CALocalProxy { public: CALocalProxy() { m_arRSA=NULL; m_pSymCipher=NULL; } ~CALocalProxy(){clean();} // signals the main loop whether to capture or replay packets static bool bCapturePackets; static bool bReplayPackets; static int iCapturedPackets; SINT32 start(); private: SINT32 loop(); SINT32 init(); SINT32 initOnce(); SINT32 clean(); SINT32 processKeyExchange(UINT8* buff,UINT32 size); private: CASocket m_socketIn; CASocket m_socketSOCKSIn; CAMuxSocket m_muxOut; UINT32 m_chainlen; UINT32 m_MixCascadeProtocolVersion; CAASymCipher* m_arRSA; CASymCipher* m_pSymCipher; }; #endif //!NEW_MIX_TYPE #endif anon-proxy-00.05.38+20081230/CALastMix.hpp0000644000175000017500000001134511126511234016212 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CALASTMIX__ #define __CALASTMIX__ #ifndef ONLY_LOCAL_PROXY #include "CAMix.hpp" #include "CAMuxSocket.hpp" #include "CAASymCipher.hpp" #include "CASocketAddrINet.hpp" #include "CACacheLoadBalancing.hpp" #include "CASignature.hpp" #include "CAUtil.hpp" #include "CAQueue.hpp" #include "CAInfoService.hpp" #ifdef LOG_CRIME #include "tre/regex.h" #endif #include "CALogPacketStats.hpp" #ifndef NEW_MIX_TYPE // not TypeB mixes /* TypeB mixes are using an own implementation */ #include "CALastMixChannelList.hpp" #endif #ifdef REPLAY_DETECTION #include "CAMixWithReplayDB.hpp" #endif THREAD_RETURN lm_loopLog(void*); THREAD_RETURN lm_loopSendToMix(void* param); THREAD_RETURN lm_loopReadFromMix(void* pParam); class CALastMix:public #ifdef REPLAY_DETECTION CAMixWithReplayDB #else CAMix #endif { public: CALastMix() { m_pMuxIn=NULL; m_pSignature=NULL; m_pRSA=NULL; m_pInfoService=NULL; #ifndef NEW_MIX_TYPE // not TypeB mixes /* TypeB mixes are using an own implementation */ m_pChannelList=NULL; #endif m_pthreadSendToMix=m_pthreadReadFromMix=NULL; m_pQueueSendToMix=m_pQueueReadFromMix=NULL; m_pCacheLB=new CACacheLoadBalancing(); m_pSocksLB=new CACacheLoadBalancing(); #ifdef LOG_PACKET_STATS m_pLogPacketStats=NULL; #endif } virtual ~CALastMix() { clean(); delete m_pCacheLB; m_pCacheLB = NULL; delete m_pSocksLB; m_pSocksLB = NULL; } SINT32 reconfigure(); tMixType getType() const { return CAMix::LAST_MIX; } protected: #ifdef DYNAMIC_MIX void stopCascade() { m_bRestart = true; } #endif virtual SINT32 loop()=0; SINT32 init(); virtual SINT32 initOnce(); SINT32 clean(); #ifdef NEW_MIX_TYPE // TypeB mixes virtual void reconfigureMix(); #endif // added by ronin SINT32 initMixCascadeInfo(DOMElement* ); // moved to CAMix.hpp virtual SINT32 processKeyExchange(); SINT32 setTargets(); #ifdef LOG_CRIME bool checkCrime(const UINT8* payLoad,UINT32 payLen); #endif protected: volatile bool m_bRestart; CAMuxSocket* m_pMuxIn; CAQueue* m_pQueueSendToMix; CAQueue* m_pQueueReadFromMix; #ifdef LOG_PACKET_TIMES CALogPacketStats* m_pLogPacketStats; #endif CACacheLoadBalancing* m_pCacheLB; CACacheLoadBalancing* m_pSocksLB; CAASymCipher* m_pRSA; CAThread* m_pthreadSendToMix; CAThread* m_pthreadReadFromMix; #ifndef NEW_MIX_TYPE // not TypeB mixes /* TypeB mixes are using an own implementation */ CALastMixChannelList* m_pChannelList; #endif #ifdef LOG_CRIME regex_t* m_pCrimeRegExpsURL; UINT32 m_nCrimeRegExpsURL; regex_t* m_pCrimeRegExpsPayload; UINT32 m_nCrimeRegExpsPayload; #endif protected: friend THREAD_RETURN lm_loopSendToMix(void* param); friend THREAD_RETURN lm_loopReadFromMix(void* pParam); friend THREAD_RETURN lm_loopLog(void*); volatile bool m_bRunLog; volatile UINT32 m_logUploadedPackets; volatile UINT64 m_logUploadedBytes; volatile UINT32 m_logDownloadedPackets; volatile UINT64 m_logDownloadedBytes; }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/CAStatusManager.cpp0000644000175000017500000004644111116234502017406 0ustar daviddavid/* Copyright (c) The JAP-Team, JonDos GmbH All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University of Technology Dresden, Germany, nor the name of the JonDos GmbH, nor the names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "CAStatusManager.hpp" #ifdef SERVER_MONITORING #include "CAMsg.hpp" #include "CAMutex.hpp" #include "CAUtil.hpp" #include "xml/DOM_Output.hpp" #include "CACmdLnOptions.hpp" #include "monitoringDefs.h" /** * @author Simon Pecher, JonDos GmbH * * Here we keep track of the current mix state to answer * server monitoring requests. */ CAStatusManager *CAStatusManager::ms_pStatusManager = NULL; state_t ***CAStatusManager::ms_pAllStates = NULL; event_t ***CAStatusManager::ms_pAllEvents = NULL; extern CACmdLnOptions* pglobalOptions; void CAStatusManager::init() { if(ms_pAllEvents == NULL) { initEvents(); } if(ms_pAllStates == NULL) { initStates(); } if(ms_pStatusManager == NULL) { ms_pStatusManager = new CAStatusManager(); } } void CAStatusManager::cleanup() { #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAStatusManager: doing cleanup\n"); #endif /*if(ms_pStatusManager->m_pStatusSocket != NULL) { if(!(ms_pStatusManager->m_pStatusSocket->isClosed())) { ms_pStatusManager->m_pStatusSocket->close(); } }*/ if(ms_pStatusManager != NULL) { delete ms_pStatusManager; ms_pStatusManager = NULL; } if(ms_pAllStates != NULL) { deleteStates(); } if(ms_pAllEvents != NULL) { deleteEvents(); } } SINT32 CAStatusManager::fireEvent(event_type_t e_type, enum status_type s_type) { if(ms_pStatusManager != NULL) { return ms_pStatusManager->transition(e_type, s_type); } else { CAMsg::printMsg(LOG_CRIT, "StatusManager: cannot handle event %d/%d " "because there is no StatusManager deployed\n", s_type, e_type); return E_UNKNOWN; } } CAStatusManager::CAStatusManager() { int i = 0, ret = 0; m_pCurrentStates = NULL; m_pCurrentStatesInfo = NULL; m_pStatusLock = NULL; m_pStatusSocket = NULL; m_pListenAddr = NULL; m_pMonitoringThread = NULL; m_pPreparedStatusMessage = NULL; m_bTryListen = false; m_pCurrentStates = new state_t*[NR_STATUS_TYPES]; for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { m_pCurrentStates[i] = ms_pAllStates[i][ENTRY_STATE]; #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Init state: %s - %s\n", STATUS_NAMES[i], m_pCurrentStates[i]->st_description); #endif } m_pStatusLock = new CAMutex(); m_pStatusSocket = new CASocket(); ret = initSocket(); if( (ret == E_SUCCESS) || (ret == EADDRINUSE) ) { m_bTryListen = (ret == EADDRINUSE); m_pMonitoringThread = new CAThread((UINT8*)"Monitoring Thread"); m_pMonitoringThread->setMainLoop(serveMonitoringRequests); m_pMonitoringThread->start(this); } else { CAMsg::printMsg(LOG_ERR, "StatusManager: an error occured while initializing the" " server monitoring socket\n"); } initStatusMessage(); /* pass entry state staus information to the DOM structure */ for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { setDOMElementValue( (m_pCurrentStatesInfo[i]).dsi_stateType, (UINT32)(m_pCurrentStates[i])->st_type); setDOMElementValue( (m_pCurrentStatesInfo[i]).dsi_stateDesc, (UINT8*)(m_pCurrentStates[i])->st_description); setDOMElementValue( (m_pCurrentStatesInfo[i]).dsi_stateLevel, (UINT8*)(STATUS_LEVEL_NAMES[(m_pCurrentStates[i])->st_stateLevel])); } } CAStatusManager::~CAStatusManager() { int i = 0; if(m_pMonitoringThread != NULL) { if(m_pStatusSocket != NULL) { if( !(m_pStatusSocket->isClosed()) ) { m_pStatusSocket->close(); } } delete m_pMonitoringThread; #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAStatusManager: The monitoring thread is no more.\n"); #endif m_pMonitoringThread = NULL; } if(m_pStatusLock != NULL) { delete m_pStatusLock; m_pStatusLock = NULL; } if(m_pCurrentStates != NULL) { for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { m_pCurrentStates[i] = NULL; } delete[] m_pCurrentStates; m_pCurrentStates = NULL; } if(m_pStatusSocket != NULL) { delete m_pStatusSocket; m_pStatusSocket = NULL; } if(m_pListenAddr != NULL) { delete m_pListenAddr; m_pListenAddr = NULL; } if(m_pPreparedStatusMessage != NULL) { m_pPreparedStatusMessage->release(); m_pPreparedStatusMessage = NULL; } } SINT32 CAStatusManager::initSocket() { SINT32 ret = E_UNKNOWN; int errnum = 0; if(m_pStatusSocket == NULL) { m_pStatusSocket = new CASocket(); } if( !(m_pStatusSocket->isClosed()) ) { CAMsg::printMsg(LOG_ERR, "StatusManager: server monitoring socket already connected.\n"); return E_UNKNOWN; } ret = m_pStatusSocket->create(); if(ret != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "StatusManager: could not create server monitoring socket.\n"); return ret; } /* listen to default server address, if nothing is specified: * localhost:8080 */ char *hostname = "localhost"; UINT16 port = MONITORING_SERVER_PORT; bool userdefined = false; if(pglobalOptions != NULL) { if(pglobalOptions->getMonitoringListenerHost()!= NULL) { hostname = pglobalOptions->getMonitoringListenerHost(); userdefined = true; } if(pglobalOptions->getMonitoringListenerPort()!= 0xFFFF) { port = pglobalOptions->getMonitoringListenerPort(); userdefined = true; } } m_pListenAddr = new CASocketAddrINet(); ret = m_pListenAddr->setAddr((UINT8 *) hostname, port); if(ret != E_SUCCESS) { if(ret == E_UNKNOWN_HOST) { CAMsg::printMsg(LOG_ERR, "StatusManager: could not initialize specified listener interface:" " invalid host %s\n", hostname); if(userdefined) { hostname = "localhost"; CAMsg::printMsg(LOG_ERR, "StatusManager: trying %s.\n", hostname); ret = m_pListenAddr->setAddr((UINT8 *) hostname, port); if(ret != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "StatusManager: setting up listener interface %s:%d for " "server monitoring failed\n", hostname, port); return ret; } } } else { CAMsg::printMsg(LOG_ERR, "StatusManager: setting up listener interface %s:%d for " "server monitoring failed\n", hostname, port); return ret; } } ret = m_pStatusSocket->listen(*m_pListenAddr); if(ret != E_SUCCESS) { if(ret != E_UNKNOWN) { errnum = GET_NET_ERROR; CAMsg::printMsg(LOG_ERR, "StatusManager: not able to init server socket %s:%d " "for server monitoring. %s failed because: %s\n", hostname, port, ((ret == E_SOCKET_BIND) ? "Bind" : "Listen"), GET_NET_ERROR_STR(errnum)); if( errnum == EADDRINUSE ) { CAMsg::printMsg(LOG_INFO, "retry socket listening later\n"); return errnum; //it's safer to avoid reuseaddr in this case } } return ret; } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "StatusManager: listen to monitoring socket on %s:%d\n", hostname, port); #endif return E_SUCCESS; } SINT32 CAStatusManager::transition(event_type_t e_type, status_type_t s_type) { transition_t transitionToNextState = st_ignore; state_t *prev = NULL; if( (m_pStatusLock == NULL) || (m_pCurrentStates == NULL) ) { CAMsg::printMsg(LOG_CRIT, "StatusManager: fatal error\n"); return E_UNKNOWN; } if((s_type >= NR_STATUS_TYPES) || (s_type < FIRST_STATUS)) { CAMsg::printMsg(LOG_ERR, "StatusManager: received event for an invalid status type: %d\n", s_type); return E_INVALID; } if((e_type >= EVENT_COUNT[s_type]) || (e_type < FIRST_EVENT)) { CAMsg::printMsg(LOG_ERR, "StatusManager: received an invalid event: %d\n", e_type); return E_INVALID; } /* We process incoming events synchronously, so the calling thread * should perform state transition very quickly to avoid long blocking * of other calling threads */ m_pStatusLock->lock(); if(m_pCurrentStates[s_type]->st_transitions == NULL) { m_pStatusLock->unlock(); CAMsg::printMsg(LOG_CRIT, "StatusManager: current state is corrupt\n"); return E_UNKNOWN; } transitionToNextState = m_pCurrentStates[s_type]->st_transitions[e_type]; if(transitionToNextState >= STATE_COUNT[s_type]) { m_pStatusLock->unlock(); CAMsg::printMsg(LOG_ERR, "StatusManager: transition to invalid state %d\n", transitionToNextState); return E_INVALID; } if(transitionToNextState != st_ignore) { prev = m_pCurrentStates[s_type]; m_pCurrentStates[s_type] = ms_pAllStates[s_type][transitionToNextState]; m_pCurrentStates[s_type]->st_prev = prev; m_pCurrentStates[s_type]->st_cause = ms_pAllEvents[s_type][e_type]; /* setting the xml elements of the info message won't be too expensive */ setDOMElementValue( (m_pCurrentStatesInfo[s_type]).dsi_stateType, (UINT32)(m_pCurrentStates[s_type])->st_type); setDOMElementValue( (m_pCurrentStatesInfo[s_type]).dsi_stateDesc, (UINT8*)(m_pCurrentStates[s_type])->st_description); setDOMElementValue( (m_pCurrentStatesInfo[s_type]).dsi_stateLevel, (UINT8*)(STATUS_LEVEL_NAMES[(m_pCurrentStates[s_type])->st_stateLevel])); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "StatusManager: status %s: " "transition from state %d (%s) " "to state %d (%s) caused by event %d (%s)\n", STATUS_NAMES[s_type], prev->st_type, prev->st_description, m_pCurrentStates[s_type]->st_type, m_pCurrentStates[s_type]->st_description, e_type, (ms_pAllEvents[s_type][e_type])->ev_description); #endif } m_pStatusLock->unlock(); return E_SUCCESS; } /* prepares (once) a DOM template for all status messages */ SINT32 CAStatusManager::initStatusMessage() { int i = 0; m_pPreparedStatusMessage = createDOMDocument(); m_pCurrentStatesInfo = new dom_state_info[NR_STATUS_TYPES]; DOMElement *elemRoot = createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATUS_MESSAGE_NAME); DOMElement *status_dom_element = NULL; for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { status_dom_element = createDOMElement(m_pPreparedStatusMessage, STATUS_NAMES[i]); (m_pCurrentStatesInfo[i]).dsi_stateType = createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATE_NAME); #ifdef DEBUG setDOMElementValue((m_pCurrentStatesInfo[i]).dsi_stateType, (UINT8*)"Statenumber"); #endif (m_pCurrentStatesInfo[i]).dsi_stateLevel = createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATE_LEVEL_NAME); #ifdef DEBUG setDOMElementValue((m_pCurrentStatesInfo[i]).dsi_stateLevel, (UINT8*)"OK or Critcal or something"); #endif (m_pCurrentStatesInfo[i]).dsi_stateDesc = createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATE_DESCRIPTION_NAME); #ifdef DEBUG setDOMElementValue((m_pCurrentStatesInfo[i]).dsi_stateDesc, (UINT8*)"Description of the state"); #endif status_dom_element->appendChild((m_pCurrentStatesInfo[i]).dsi_stateType); status_dom_element->appendChild((m_pCurrentStatesInfo[i]).dsi_stateLevel); status_dom_element->appendChild((m_pCurrentStatesInfo[i]).dsi_stateDesc); elemRoot->appendChild(status_dom_element); } m_pPreparedStatusMessage->appendChild(elemRoot); #ifdef DEBUG UINT32 debuglen = XML_STATUS_MESSAGE_MAX_SIZE - 1; UINT8 debugout[XML_STATUS_MESSAGE_MAX_SIZE]; memset(debugout, 0, (sizeof(UINT8)*XML_STATUS_MESSAGE_MAX_SIZE)); DOM_Output::dumpToMem(m_pPreparedStatusMessage,debugout,&debuglen); CAMsg::printMsg(LOG_DEBUG, "the status message template looks like this: %s \n",debugout); #endif return E_SUCCESS; } THREAD_RETURN serveMonitoringRequests(void* param) { CASocket monitoringRequestSocket; int ret = 0; CAStatusManager *statusManager = (CAStatusManager*) param; if(statusManager == NULL) { CAMsg::printMsg(LOG_CRIT, "Monitoring Thread: fatal error, exiting.\n"); THREAD_RETURN_ERROR; } for(;EVER;) { if(statusManager->m_pStatusSocket != NULL) { if(statusManager->m_bTryListen) { sleep(10); if(statusManager->m_pListenAddr == NULL) { CAMsg::printMsg(LOG_ERR, "Monitoring Thread: bind error, leaving loop.\n"); THREAD_RETURN_ERROR; } ret = statusManager-> m_pStatusSocket->listen(*(statusManager->m_pListenAddr)); if(ret == E_UNKNOWN) { CAMsg::printMsg(LOG_ERR, "Monitoring Thread: bind error, leaving loop.\n"); THREAD_RETURN_ERROR; } statusManager->m_bTryListen = (ret != E_SUCCESS); #ifdef DEBUG if(statusManager->m_bTryListen) { CAMsg::printMsg(LOG_DEBUG, "Monitoring Thread: wait again for listen: %s\n", GET_NET_ERROR_STR(GET_NET_ERROR)); } else { CAMsg::printMsg(LOG_DEBUG, "Monitoring Thread: socket listening again\n"); } #endif continue; } if(statusManager->m_pStatusSocket->isClosed()) { CAMsg::printMsg(LOG_INFO, "Monitoring Thread: server socket closed, leaving loop.\n"); THREAD_RETURN_SUCCESS; } } else { CAMsg::printMsg(LOG_ERR, "Monitoring Thread: server socket disposed, leaving loop.\n"); THREAD_RETURN_ERROR; } if(statusManager->m_pStatusSocket->accept(monitoringRequestSocket) == E_SUCCESS) { UINT32 xmlStatusMessageLength = XML_STATUS_MESSAGE_MAX_SIZE - 1; char xmlStatusMessage[XML_STATUS_MESSAGE_MAX_SIZE]; memset(xmlStatusMessage, 0, (sizeof(char)*XML_STATUS_MESSAGE_MAX_SIZE)); statusManager->m_pStatusLock->lock(); DOM_Output::dumpToMem( statusManager->m_pPreparedStatusMessage, (UINT8*)xmlStatusMessage, &xmlStatusMessageLength); statusManager->m_pStatusLock->unlock(); char http_prefix[HTTP_ANSWER_PREFIX_MAX_LENGTH]; memset(http_prefix, 0, (sizeof(char)*HTTP_ANSWER_PREFIX_MAX_LENGTH)); snprintf(http_prefix, HTTP_ANSWER_PREFIX_MAX_LENGTH, HTTP_ANSWER_PREFIX_FORMAT, xmlStatusMessageLength); size_t http_prefix_length = strlen(http_prefix); char statusMessageResponse[http_prefix_length+xmlStatusMessageLength+1]; strncpy(statusMessageResponse, http_prefix, http_prefix_length); strncpy((statusMessageResponse+http_prefix_length), xmlStatusMessage, xmlStatusMessageLength); statusMessageResponse[xmlStatusMessageLength+http_prefix_length]=0; #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "the status message looks like this: %s \n",statusMessageResponse); #endif if(monitoringRequestSocket.send((UINT8*)statusMessageResponse, (http_prefix_length+xmlStatusMessageLength)) < 0) { CAMsg::printMsg(LOG_ERR, "StatusManager: error: could not send status message.\n"); } monitoringRequestSocket.close(); } else { CAMsg::printMsg(LOG_ERR, "StatusManager: error: could not process monitoring request.\n"); } } } void CAStatusManager::initStates() { int i = 0, j = 0; ms_pAllStates = new state_t**[NR_STATUS_TYPES]; for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { ms_pAllStates[i] = new state_t*[STATE_COUNT[i]]; for(j = ENTRY_STATE; j < STATE_COUNT[i]; j++) { ms_pAllStates[i][j] = new state_t; /* only state identifier are set, transitions and state description * must be set via macro **/ ms_pAllStates[i][j]->st_type = (state_type_t) j; ms_pAllStates[i][j]->st_statusType = (status_type_t) i; } } FINISH_STATE_DEFINITIONS(ms_pAllStates); } void CAStatusManager::deleteStates() { int i = 0, j = 0; for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { //m_pCurrentStates[i] = NULL; for(j = ENTRY_STATE; j < STATE_COUNT[i]; j++) { if(ms_pAllStates[i][j] != NULL) { if(ms_pAllStates[i][j]->st_transitions != NULL) { delete[] ms_pAllStates[i][j]->st_transitions; ms_pAllStates[i][j]->st_transitions = NULL; } //todo: delete state descriptions ? delete ms_pAllStates[i][j]; ms_pAllStates[i][j] = NULL; } } delete[] ms_pAllStates[i]; ms_pAllStates[i] = NULL; } delete[] ms_pAllStates; ms_pAllStates = NULL; } void CAStatusManager::initEvents() { int i = 0, j = 0; ms_pAllEvents = new event_t**[NR_STATUS_TYPES]; for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { ms_pAllEvents[i] = new event_t*[EVENT_COUNT[i]]; for(j = FIRST_EVENT; j < EVENT_COUNT[i]; j++) { ms_pAllEvents[i][j] = new event_t; ms_pAllEvents[i][j]->ev_type = (event_type_t) j; ms_pAllEvents[i][j]->ev_statusType = (status_type_t) i; } } FINISH_EVENT_DEFINITIONS(ms_pAllEvents); } void CAStatusManager::deleteEvents() { int i = 0, j = 0; for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++) { for(j = FIRST_EVENT; j < EVENT_COUNT[i]; j++) { //todo: delete event descriptions ? delete ms_pAllEvents[i][j]; ms_pAllEvents[i][j] = NULL; } delete[] ms_pAllEvents[i]; ms_pAllEvents[i] = NULL; } delete[] ms_pAllEvents; ms_pAllEvents = NULL; } transition_t *defineTransitions(status_type_t s_type, SINT32 transitionCount, ...) { int i = 0; va_list ap; transition_t *transitions = NULL; event_type_t specifiedEventTypes[transitionCount]; transition_t specifiedTransitions[transitionCount]; /* read in the specified events with the corresponding transitions */ va_start(ap, transitionCount); for(i = 0; i < transitionCount; i++) { specifiedEventTypes[i] = (event_type_t) va_arg(ap, int); specifiedTransitions[i] = (transition_t) va_arg(ap, int); } va_end(ap); if((s_type >= NR_STATUS_TYPES) || (s_type < FIRST_STATUS)) { /* invalid status type specified */ return NULL; } if(transitionCount > (EVENT_COUNT[s_type])) { /* more transitions specified than events defined*/ return NULL; } transitions = new transition_t[(EVENT_COUNT[s_type])]; memset(transitions, st_ignore, (sizeof(transition_t)*(EVENT_COUNT[s_type]))); for(i = 0; i < transitionCount; i++) { if((specifiedEventTypes[i] >= EVENT_COUNT[s_type]) || (specifiedEventTypes[i] < 0)) { /* specified event is invalid */ CAMsg::printMsg(LOG_WARNING, "StatusManager: definition of an invalid state transition (invalid event %d).\n", specifiedEventTypes[i]); continue; } if((specifiedTransitions[i] >= STATE_COUNT[s_type]) || (specifiedTransitions[i] < st_ignore)) { /* corresponding transition to event is not valid */ CAMsg::printMsg(LOG_WARNING, "StatusManager: definition of an invalid state transition (invalid state %d).\n", specifiedTransitions[i]); continue; } transitions[specifiedEventTypes[i]] = specifiedTransitions[i]; } /*for(i=0; i < (EVENT_COUNT[s_type]); i++) { CAMsg::printMsg(LOG_DEBUG, "transitions %d: %d\n", i, transitions[i]); }*/ return transitions; } #endif anon-proxy-00.05.38+20081230/CAXMLBI.hpp0000644000175000017500000000645510763256462015531 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CAXMLBI__ #define __CAXMLBI__ #if !defined (ONLY_LOCAL_PROXY) && defined(PAYMENT) #include "CAAbstractXMLEncodable.hpp" #include "CACertificate.hpp" #include "CASignature.hpp" #include "CAUtil.hpp" /** * This class contains the parameters needed for * talking to a BI (payment instance - bezahlinstanz). * It corresponds to anon.pay.BI in the Java implementation * @author Bastian Voigt (bavoigt@inf.fu-berlin.de) */ class CAXMLBI : public CAAbstractXMLEncodable { public: static CAXMLBI* getInstance(const UINT8 * biID, const UINT8 * hostName, const int portNumber, CACertificate * pCert); static CAXMLBI* getInstance(DOMElement* elemRoot); ~CAXMLBI(); /** returns the BI's unique name (identifier) */ UINT8 * getID() { return m_pBiID; } /** returns a CASignature object for veriying this BI's signatures * Don't delete it because it is 0wned by this! */ CASignature * getVerifier() { if (!m_pVeryfire) { m_pVeryfire = new CASignature; m_pVeryfire->setVerifyKey(m_pCert); } return m_pVeryfire; } /** returns the hostname of the host on which this BI is running */ UINT8* getHostName() { return m_pHostName; } /** gets the port number */ UINT32 getPortNumber() { return m_iPortNumber; } SINT32 toXmlElement( XERCES_CPP_NAMESPACE::DOMDocument* a_doc, DOMElement* & elemRoot); CACertificate* getCertificate() { return m_pCert; } static const char* const getXMLElementName() { return CAXMLBI::ms_pXmlElemName; } private: SINT32 setValues(DOMElement* elemRoot); UINT8 * m_pBiID; UINT8 * m_pHostName; CACertificate * m_pCert; CASignature * m_pVeryfire; UINT32 m_iPortNumber; CAXMLBI(); static const char* const ms_pXmlElemName; }; #endif //ONLY_LOCAL_PROXY #endif anon-proxy-00.05.38+20081230/gcm/0000755000175000017500000000000011126517130014457 5ustar daviddavidanon-proxy-00.05.38+20081230/gcm/gcm.cpp0000644000175000017500000007157611122445202015745 0ustar daviddavid#include "../StdAfx.h" #include "gcm.h" static void mul_alpha(UINT32 *z) { int carry = z[3] & 1; z[3] >>= 1; z[3] |= ((z[2] & 1) << 31); z[2] >>= 1; z[2] |= ((z[1] & 1) << 31); z[1] >>= 1; z[1] |= ((z[0] & 1) << 31); z[0] >>= 1; if (carry) z[0] ^= GHASH_ALPHA; } static void build_hash_table_64k(gcm_ctx_64k *c, UINT32 hkey[4]) { UINT32 a[4]; int i, j, k, t; a[0] = htonl(hkey[0]); a[1] = htonl(hkey[1]); a[2] = htonl(hkey[2]); a[3] = htonl(hkey[3]); for (t=0;t<16;t++) { c->table[t][0][0] = c->table[t][0][1] = c->table[t][0][2] = c->table[t][0][3] = 0; i = 128, j = 256; while (i) { c->table[t][i][0] = htonl(a[0]); c->table[t][i][1] = htonl(a[1]); c->table[t][i][2] = htonl(a[2]); c->table[t][i][3] = htonl(a[3]); mul_alpha(a); i >>= 1; j >>= 1; } } for (i=1;i<256;i<<=1) { for (j=1;jtable[t][k][0] = c->table[t][i][0] ^ c->table[t][j][0]; c->table[t][k][1] = c->table[t][i][1] ^ c->table[t][j][1]; c->table[t][k][2] = c->table[t][i][2] ^ c->table[t][j][2]; c->table[t][k][3] = c->table[t][i][3] ^ c->table[t][j][3]; } } } } #if BYTE_ORDER == BIG_ENDIAN #define GMULWI64K(e,t,i,s) \ e = (UINT32 *)t[i][s>>24]; t0 = e[0]; t1 = e[1]; t2 = e[2]; t3 = e[3];\ e = (UINT32 *)t[i+1][(s>>16)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+2][(s>>8)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+3][s&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3] #define GMULW64K(e,t,i,s) \ e = (UINT32 *)t[i][s>>24]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+1][(s>>16)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+2][(s>>8)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+3][s&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3] #else #define GMULWI64K(e,t,i,s) \ e = (UINT32 *)t[i][s&0xff]; t0 = e[0]; t1 = e[1]; t2 = e[2]; t3 = e[3];\ e = (UINT32 *)t[i+1][(s>>8)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+2][(s>>16)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+3][s>>24]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3] #define GMULW64K(e,t,i,s) \ e = (UINT32 *)t[i][s&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+1][(s>>8)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+2][(s>>16)&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ e = (UINT32 *)t[i+3][s>>24]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3] #endif #define GHB64K(t, b) \ s0 ^= ((UINT32 *)b)[0]; \ s1 ^= ((UINT32 *)b)[1]; \ s2 ^= ((UINT32 *)b)[2]; \ s3 ^= ((UINT32 *)b)[3]; \ GMULWI64K(entry, t, 0, s0);\ GMULW64K(entry, t, 4, s1);\ GMULW64K(entry, t, 8, s2);\ GMULW64K(entry, t, 12, s3);\ s0 = t0; \ s1 = t1; \ s2 = t2; \ s3 = t3; MODIFIERS void gcm_init_64k(gcm_ctx_64k *c, UINT8 key[], size_t keylen) { UINT32 hkgen[4] = {0,}; UINT32 hkey[4]; if (keylen != 128 && keylen != 192 && keylen != 256) { return; } ENCRYPT_INIT(&(c->ck), key, keylen); c->keylen = keylen; DO_ENCRYPT(&(c->ck), (UINT8 *)hkgen, (UINT8 *)hkey, keylen); build_hash_table_64k(c, hkey); } MODIFIERS void inline gcm_encrypt_64k(gcm_ctx_64k *c, UINT8 *nonce, size_t nlen, UINT8 *data, size_t dlen, UINT8 *adata, size_t alen, UINT8 *out, UINT8 *tag) { UINT32 tmp[8] = {0, 0, 0, 0, 0, htonl(alen << 3), 0, htonl(dlen << 3)}; UINT32 ctr[4]; size_t b, l, i; register UINT32 t0, t1, t2, t3; register UINT32 *entry; register UINT32 s0 = 0, s1 = 0, s2 = 0, s3 = 0; /* Process the nonce first. */ if (nlen != 12) { b = nlen >> 4; l = nlen & 15; while (b--) { GHB64K(c->table, nonce); nonce += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = nonce[l]; GHB64K(c->table, tmp); } tmp[0] = tmp[1] = 0; tmp[2] = htonl(nlen >> 29); tmp[3] = htonl(nlen << 3); GHB64K(c->table, tmp); ctr[0] = s0; ctr[1] = s1; ctr[2] = s2; ctr[3] = htonl(s3); tmp[0] = tmp[1] = tmp[2] = tmp[3] = s0 = s1 = s2 = s3 = 0; } else { ctr[0] = ((UINT32 *)nonce)[0]; ctr[1] = ((UINT32 *)nonce)[1]; ctr[2] = ((UINT32 *)nonce)[2]; ctr[3] = 1; } CTR_INIT(&(c->ck), ctr, ctr + 3, tag, c->keylen); /* Hash associated data. */ if (alen) { b = alen >> 4; l = alen & 15; for (i=0;itable, adata); adata += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = adata[l]; GHB64K(c->table, tmp); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; } } /* Hash ciphertext. */ b = dlen >> 4; l = dlen & 15; for (i=0;ick), (&ctr[3]), out, c->keylen); ((UINT32 *)out)[0] ^= ((UINT32 *)data)[0]; ((UINT32 *)out)[1] ^= ((UINT32 *)data)[1]; ((UINT32 *)out)[2] ^= ((UINT32 *)data)[2]; ((UINT32 *)out)[3] ^= ((UINT32 *)data)[3]; GHB64K(c->table, out); data += GHASH_BLK_SZ; out += GHASH_BLK_SZ; } if (l) { CTR_ENCRYPT(&(c->ck), &ctr[3], ctr, c->keylen); for (i=0;itable, tmp); } GHB64K(c->table, (tmp + 4)); ((UINT32 *)tag)[0] ^= s0; ((UINT32 *)tag)[1] ^= s1; ((UINT32 *)tag)[2] ^= s2; ((UINT32 *)tag)[3] ^= s3; } MODIFIERS int gcm_decrypt_64k(gcm_ctx_64k *c, UINT8 *nonce, size_t nlen, UINT8 *ct, size_t ctlen, UINT8 *tag, size_t taglen, UINT8 *adata, size_t alen, UINT8 *pt) { UINT32 tmp[8] = {0, 0, 0, 0, htonl(alen >> 29), htonl(alen << 3), htonl(ctlen >> 29), htonl(ctlen << 3)}; UINT32 ctr[4]; UINT8 chksm[16]; register char *p; size_t b, l, i; register UINT32 t0, t1, t2, t3; register UINT32 *entry; register UINT32 s0 = 0, s1 = 0, s2 = 0, s3 = 0; if (taglen > 16) taglen = 16; if (nlen != 12) { b = nlen >> 4; l = nlen & 15; while (b--) { GHB64K(c->table, nonce); nonce += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = nonce[l]; GHB64K(c->table, tmp); } tmp[0] = tmp[1] = 0; tmp[2] = htonl(nlen >> 29); tmp[3] = htonl(nlen << 3); GHB64K(c->table, tmp); ctr[0] = s0; ctr[1] = s1; ctr[2] = s2; ctr[3] = htonl(s3); tmp[0] = tmp[1] = tmp[2] = tmp[3] = s0 = s1 = s2 = s3 = 0; } else { ctr[0] = ((UINT32 *)nonce)[0]; ctr[1] = ((UINT32 *)nonce)[1]; ctr[2] = ((UINT32 *)nonce)[2]; ctr[3] = 1; } CTR_INIT(&(c->ck), ctr, ctr + 3, chksm, c->keylen); for (i=0;i> 4; l = alen & 15; for (i=0;itable, adata); adata += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = adata[l]; GHB64K(c->table, tmp); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; } } b = ctlen >> 4; l = ctlen & 15; p = (char*)ct; for (i=0;itable, p); p += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = p[l]; GHB64K(c->table, tmp); } l = ctlen & 15; GHB64K(c->table, (tmp + 4)); ((UINT32 *)chksm)[0] ^= s0; ((UINT32 *)chksm)[1] ^= s1; ((UINT32 *)chksm)[2] ^= s2; ((UINT32 *)chksm)[3] ^= s3; for (i=taglen;i<16;i++) chksm[i] = 0; if (((UINT32 *)chksm)[0] || ((UINT32 *)chksm)[1] || ((UINT32 *)chksm)[2] || ((UINT32 *)chksm)[3]) return 0; for (i=0;ick), (&ctr[3]), pt, c->keylen); ((UINT32 *)pt)[0] ^= ((UINT32 *)ct)[0]; ((UINT32 *)pt)[1] ^= ((UINT32 *)ct)[1]; ((UINT32 *)pt)[2] ^= ((UINT32 *)ct)[2]; ((UINT32 *)pt)[3] ^= ((UINT32 *)ct)[3]; ct += GHASH_BLK_SZ; pt += GHASH_BLK_SZ; } if (l) { CTR_ENCRYPT(&(c->ck), &ctr[3], ctr, c->keylen); for (i=0;itable[0][0] = c->table[0][1] = c->table[0][2] = c->table[0][3] = 0; w = htonl(hkey[0]); x = htonl(hkey[1]); y = htonl(hkey[2]); z = htonl(hkey[3]); c->table[0x80][0] = w; c->table[0x80][1] = x; c->table[0x80][2] = y; c->table[0x80][3] = z; while (i) { carry = z & 1; z >>= 1; z |= (y & 1) << 31; y >>= 1; y |= (x & 1) << 31; x >>= 1; x |= (w & 1) << 31; w >>= 1; if (carry) w ^= GHASH_ALPHA; c->table[i][0] = w; c->table[i][1] = x; c->table[i][2] = y; c->table[i][3] = z; i >>= 1; } for (i=1;i<256;i<<=1) { for (j=1;jtable[k][0] = c->table[i][0] ^ c->table[j][0]; c->table[k][1] = c->table[i][1] ^ c->table[j][1]; c->table[k][2] = c->table[i][2] ^ c->table[j][2]; c->table[k][3] = c->table[i][3] ^ c->table[j][3]; } } } #define SHIFT4K() \ tt = t3 & 0xff; t3 >>= 8; t3 |= (t2 << 24); t2 >>= 8; t2 |= (t1 << 24);\ t1 >>= 8; t1 |= (t0 << 24); t0 >>=8; t0 ^= rtable_4k[tt] #define GMULWI4K(e,t,s) \ e = (UINT32 *)t[s&0xff]; t0 = e[0]; t1 = e[1]; t2 = e[2]; t3 = e[3];\ SHIFT4K();\ e = (UINT32 *)t[(s>>8)&0xff];t0 ^= e[0];t1 ^= e[1];t2 ^= e[2];t3 ^= e[3];\ SHIFT4K();\ e = (UINT32 *)t[(s>>16)&0xff];t0 ^= e[0];t1 ^= e[1];t2 ^= e[2];t3 ^= e[3];\ SHIFT4K();\ e = (UINT32 *)t[s>>24];t0 ^= e[0];t1 ^= e[1];t2 ^= e[2];t3 ^= e[3] #define GMULW4K(e,t,s) \ SHIFT4K();\ e = (UINT32 *)t[s&0xff]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ SHIFT4K();\ e = (UINT32 *)t[(s>>8)&0xff];t0 ^= e[0];t1 ^= e[1];t2 ^= e[2];t3 ^= e[3];\ SHIFT4K();\ e = (UINT32 *)t[(s>>16)&0xff];t0 ^= e[0];t1 ^= e[1];t2 ^= e[2];t3 ^= e[3];\ SHIFT4K();\ e = (UINT32 *)t[s>>24];t0 ^= e[0];t1 ^= e[1];t2 ^= e[2];t3 ^= e[3]; #define GHB4K(t,b)\ s0 ^= htonl(((UINT32 *)b)[0]); \ s1 ^= htonl(((UINT32 *)b)[1]); \ s2 ^= htonl(((UINT32 *)b)[2]); \ s3 ^= htonl(((UINT32 *)b)[3]); \ GMULWI4K(entry, t, s3); \ GMULW4K(entry, t, s2);\ GMULW4K(entry, t, s1);\ GMULW4K(entry, t, s0);\ s0 = t0; \ s1 = t1; \ s2 = t2; \ s3 = t3; MODIFIERS void gcm_init_4k(gcm_ctx_4k *c, UINT8 key[16], size_t keylen) { UINT32 hkgen[4] = {0,}; UINT32 hkey[4]; c->keylen = keylen; ENCRYPT_INIT(&(c->ck), key, keylen); DO_ENCRYPT(&(c->ck), (UINT8 *)hkgen, (UINT8 *)hkey, keylen); build_hash_table_4k(c, hkey); } MODIFIERS void gcm_encrypt_4k(gcm_ctx_4k *c, UINT8 *nonce, size_t nlen, UINT8 *data, size_t dlen, UINT8 *adata, size_t alen, UINT8 *out, UINT8 *tag) { UINT32 tmp[8] = {0, 0, 0, 0, 0, htonl(alen << 3), 0, htonl(dlen << 3)}; UINT32 ctr[4]; size_t b, l, i; register UINT32 t0, t1, t2, t3, tt; register UINT32 *entry; register UINT32 s0 = 0, s1 = 0, s2 = 0, s3 = 0; if (nlen != 12) { b = nlen >> 4; l = nlen & 15; while (b--) { GHB4K(c->table, nonce); nonce += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = nonce[l]; GHB4K(c->table, tmp); } tmp[0] = tmp[1] = 0; tmp[2] = htonl(nlen >> 29); tmp[3] = htonl(nlen << 3); GHB4K(c->table, tmp); ctr[0] = htonl(s0); ctr[1] = htonl(s1); ctr[2] = htonl(s2); ctr[3] = s3; tmp[0] = tmp[1] = tmp[2] = tmp[3] = s0 = s1 = s2 = s3 = 0; } else { ctr[0] = ((UINT32 *)nonce)[0]; ctr[1] = ((UINT32 *)nonce)[1]; ctr[2] = ((UINT32 *)nonce)[2]; ctr[3] = 1; } CTR_INIT(&(c->ck), ctr, ctr+3, tag, c->keylen); if (alen) { b = alen >> 4; l = alen & 15; for (i=0;itable, adata); adata += 16; } if (l) { while (l--) ((UINT8 *)tmp)[l] = adata[l]; GHB4K(c->table, tmp); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; } } b = dlen >> 4; l = dlen & 15; for (i=0;ick), &ctr[3], out, c->keylen); ((UINT32 *)out)[0] ^= ((UINT32 *)data)[0]; ((UINT32 *)out)[1] ^= ((UINT32 *)data)[1]; ((UINT32 *)out)[2] ^= ((UINT32 *)data)[2]; ((UINT32 *)out)[3] ^= ((UINT32 *)data)[3]; GHB4K(c->table, out); data += GHASH_BLK_SZ; out += GHASH_BLK_SZ; } if (l) { CTR_ENCRYPT(&(c->ck), &ctr[3], ctr, c->keylen); for (i=0;itable, tmp); } GHB4K(c->table, (tmp + 4)); ((UINT32 *)tag)[0] ^= htonl(s0); ((UINT32 *)tag)[1] ^= htonl(s1); ((UINT32 *)tag)[2] ^= htonl(s2); ((UINT32 *)tag)[3] ^= htonl(s3); } MODIFIERS int gcm_decrypt_4k(gcm_ctx_4k *c, UINT8 *nonce, size_t nlen, UINT8 *ct, size_t dlen, UINT8 *stag, size_t taglen, UINT8 *adata, size_t alen, UINT8 *out) { UINT32 tmp[8] = {0, 0, 0, 0, 0, htonl(alen << 3), 0, htonl(dlen << 3)}; UINT32 ctr[4]; UINT8 tag[16], *p = ct; size_t b, l, i; register UINT32 t0, t1, t2, t3, tt; register UINT32 *entry; register UINT32 s0 = 0, s1 = 0, s2 = 0, s3 = 0; if (taglen > 16) taglen = 16; if (nlen != 12) { b = nlen >> 4; l = nlen & 15; while (b--) { GHB4K(c->table, nonce); nonce += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = nonce[l]; GHB4K(c->table, tmp); } tmp[0] = tmp[1] = 0; tmp[2] = htonl(nlen >> 29); tmp[3] = htonl(nlen << 3); GHB4K(c->table, tmp); ctr[0] = htonl(s0); ctr[1] = htonl(s1); ctr[2] = htonl(s2); ctr[3] = s3; tmp[0] = tmp[1] = tmp[2] = tmp[3] = s0 = s1 = s2 = s3 = 0; } else { ctr[0] = ((UINT32 *)nonce)[0]; ctr[1] = ((UINT32 *)nonce)[1]; ctr[2] = ((UINT32 *)nonce)[2]; ctr[3] = 1; } CTR_INIT(&(c->ck), ctr, ctr+3, tag, c->keylen); for (i=0;i> 4; l = alen & 15; for (i=0;itable, adata); adata += 16; } if (l) { while (l--) ((UINT8 *)tmp)[l] = adata[l]; GHB4K(c->table, tmp); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; } } b = dlen >> 4; l = dlen & 15; for (i=0;itable, p); p += GHASH_BLK_SZ; } if (l) { memcpy(tmp, p, l); GHB4K(c->table, tmp); } GHB4K(c->table, (tmp + 4)); ((UINT32 *)tag)[0] ^= htonl(s0); ((UINT32 *)tag)[1] ^= htonl(s1); ((UINT32 *)tag)[2] ^= htonl(s2); ((UINT32 *)tag)[3] ^= htonl(s3); for (i=taglen;i<16;i++) { tag[i] = 0; } if (((UINT32 *)tag)[0] || ((UINT32 *)tag)[1] || ((UINT32 *)tag)[2] || ((UINT32 *)tag)[3]) return 0; for (i=0;ick), &ctr[3], out, c->keylen); ((UINT32 *)out)[0] ^= ((UINT32 *)ct)[0]; ((UINT32 *)out)[1] ^= ((UINT32 *)ct)[1]; ((UINT32 *)out)[2] ^= ((UINT32 *)ct)[2]; ((UINT32 *)out)[3] ^= ((UINT32 *)ct)[3]; ct += GHASH_BLK_SZ; out += GHASH_BLK_SZ; } if (l) { CTR_ENCRYPT(&(c->ck), &ctr[3], ctr, c->keylen); for (i=0;itable[0][0] = c->table[0][1] = c->table[0][2] = c->table[0][3] = 0; c->table[0x8][0] = htonl(hkey[0]); c->table[0x8][1] = htonl(hkey[1]); c->table[0x8][2] = htonl(hkey[2]); c->table[0x8][3] = htonl(hkey[3]); c->table[0x4][0] = c->table[0x8][0]; c->table[0x4][1] = c->table[0x8][1]; c->table[0x4][2] = c->table[0x8][2]; c->table[0x4][3] = c->table[0x8][3]; mul_alpha(c->table[0x4]); c->table[0x2][0] = c->table[0x4][0]; c->table[0x2][1] = c->table[0x4][1]; c->table[0x2][2] = c->table[0x4][2]; c->table[0x2][3] = c->table[0x4][3]; mul_alpha(c->table[0x2]); c->table[0x1][0] = c->table[0x2][0]; c->table[0x1][1] = c->table[0x2][1]; c->table[0x1][2] = c->table[0x2][2]; c->table[0x1][3] = c->table[0x2][3]; mul_alpha(c->table[0x1]); c->table[0x3][0] = c->table[0x1][0] ^ c->table[0x2][0]; c->table[0x3][1] = c->table[0x1][1] ^ c->table[0x2][1]; c->table[0x3][2] = c->table[0x1][2] ^ c->table[0x2][2]; c->table[0x3][3] = c->table[0x1][3] ^ c->table[0x2][3]; c->table[0x5][0] = c->table[0x1][0] ^ c->table[0x4][0]; c->table[0x5][1] = c->table[0x1][1] ^ c->table[0x4][1]; c->table[0x5][2] = c->table[0x1][2] ^ c->table[0x4][2]; c->table[0x5][3] = c->table[0x1][3] ^ c->table[0x4][3]; c->table[0x6][0] = c->table[0x4][0] ^ c->table[0x2][0]; c->table[0x6][1] = c->table[0x4][1] ^ c->table[0x2][1]; c->table[0x6][2] = c->table[0x4][2] ^ c->table[0x2][2]; c->table[0x6][3] = c->table[0x4][3] ^ c->table[0x2][3]; c->table[0x7][0] = c->table[0x4][0] ^ c->table[0x3][0]; c->table[0x7][1] = c->table[0x4][1] ^ c->table[0x3][1]; c->table[0x7][2] = c->table[0x4][2] ^ c->table[0x3][2]; c->table[0x7][3] = c->table[0x4][3] ^ c->table[0x3][3]; c->table[0x9][0] = c->table[0x1][0] ^ c->table[0x8][0]; c->table[0x9][1] = c->table[0x1][1] ^ c->table[0x8][1]; c->table[0x9][2] = c->table[0x1][2] ^ c->table[0x8][2]; c->table[0x9][3] = c->table[0x1][3] ^ c->table[0x8][3]; c->table[0xa][0] = c->table[0x2][0] ^ c->table[0x8][0]; c->table[0xa][1] = c->table[0x2][1] ^ c->table[0x8][1]; c->table[0xa][2] = c->table[0x2][2] ^ c->table[0x8][2]; c->table[0xa][3] = c->table[0x2][3] ^ c->table[0x8][3]; c->table[0xb][0] = c->table[0x3][0] ^ c->table[0x8][0]; c->table[0xb][1] = c->table[0x3][1] ^ c->table[0x8][1]; c->table[0xb][2] = c->table[0x3][2] ^ c->table[0x8][2]; c->table[0xb][3] = c->table[0x3][3] ^ c->table[0x8][3]; c->table[0xc][0] = c->table[0x4][0] ^ c->table[0x8][0]; c->table[0xc][1] = c->table[0x4][1] ^ c->table[0x8][1]; c->table[0xc][2] = c->table[0x4][2] ^ c->table[0x8][2]; c->table[0xc][3] = c->table[0x4][3] ^ c->table[0x8][3]; c->table[0xd][0] = c->table[0x5][0] ^ c->table[0x8][0]; c->table[0xd][1] = c->table[0x5][1] ^ c->table[0x8][1]; c->table[0xd][2] = c->table[0x5][2] ^ c->table[0x8][2]; c->table[0xd][3] = c->table[0x5][3] ^ c->table[0x8][3]; c->table[0xe][0] = c->table[0x6][0] ^ c->table[0x8][0]; c->table[0xe][1] = c->table[0x6][1] ^ c->table[0x8][1]; c->table[0xe][2] = c->table[0x6][2] ^ c->table[0x8][2]; c->table[0xe][3] = c->table[0x6][3] ^ c->table[0x8][3]; c->table[0xf][0] = c->table[0x7][0] ^ c->table[0x8][0]; c->table[0xf][1] = c->table[0x7][1] ^ c->table[0x8][1]; c->table[0xf][2] = c->table[0x7][2] ^ c->table[0x8][2]; c->table[0xf][3] = c->table[0x7][3] ^ c->table[0x8][3]; } #define SHIFT256B() \ tt = t3 & 0xf; t3 >>= 4; t3 |= (t2 << 28); t2 >>= 4; t2 |= (t1 << 28);\ t1 >>= 4; t1 |= (t0 << 28); t0 >>=4; t0 ^= rtable_256b[tt] #define GMULWI256B(e,t,s) \ e = (UINT32 *)t[s&0xf]; t0 = e[0]; t1 = e[1]; t2 = e[2]; t3 = e[3];\ SHIFT256B();\ e = (UINT32 *)t[(s>>4)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ SHIFT256B();\ e = (UINT32 *)t[(s>>8)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ SHIFT256B();\ e = (UINT32 *)t[(s>>12)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[(s>>16)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[(s>>20)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[(s>>24)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[s>>28]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3] #define GMULW256B(e,t,s) \ SHIFT256B();\ e = (UINT32 *)t[s&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ SHIFT256B();\ e = (UINT32 *)t[(s>>4)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ SHIFT256B();\ e = (UINT32 *)t[(s>>8)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ SHIFT256B();\ e = (UINT32 *)t[(s>>12)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[(s>>16)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[(s>>20)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[(s>>24)&0xf]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3];\ \ SHIFT256B();\ e = (UINT32 *)t[s>>28]; t0 ^= e[0]; t1 ^= e[1]; t2 ^= e[2]; t3 ^= e[3] #define GHB256B(t,b)\ s0 ^= htonl(((UINT32 *)b)[0]); \ s1 ^= htonl(((UINT32 *)b)[1]); \ s2 ^= htonl(((UINT32 *)b)[2]); \ s3 ^= htonl(((UINT32 *)b)[3]); \ GMULWI256B(entry, t, s3); \ GMULW256B(entry, t, s2);\ GMULW256B(entry, t, s1);\ GMULW256B(entry, t, s0);\ s0 = t0; \ s1 = t1; \ s2 = t2; \ s3 = t3; void gcm_init_256b(gcm_ctx_256b *c, UINT8 key[16], size_t keylen) { UINT32 hkgen[4] = {0,}; UINT32 hkey[4]; c->keylen = keylen; ENCRYPT_INIT(&(c->ck), key, keylen); DO_ENCRYPT(&(c->ck), (UINT8 *)hkgen, (UINT8 *)hkey, keylen); build_hash_table_256b(c, hkey); } MODIFIERS void inline gcm_encrypt_256b(gcm_ctx_256b *c, UINT8 *nonce, size_t nlen, UINT8 *data, size_t dlen, UINT8 *adata, size_t alen, UINT8 *out, UINT8 *tag) { UINT32 tmp[8] = {0, 0, 0, 0, 0, htonl(alen << 3), 0, htonl(dlen << 3)}; UINT32 ctr[4]; size_t b, l, i; register UINT32 t0, t1, t2, t3, tt; register UINT32 *entry; register UINT32 s0 = 0, s1 = 0, s2 = 0, s3 = 0; /* Process the nonce first. */ if (nlen != 12) { b = nlen >> 4; l = nlen & 15; while (b--) { GHB256B(c->table, nonce); nonce += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = nonce[l]; GHB256B(c->table, tmp); } tmp[0] = tmp[1] = 0; tmp[2] = htonl(nlen >> 29); tmp[3] = htonl(nlen << 3); GHB256B(c->table, tmp); ctr[0] = htonl(s0); ctr[1] = htonl(s1); ctr[2] = htonl(s2); ctr[3] = s3; tmp[0] = tmp[1] = tmp[2] = tmp[3] = s0 = s1 = s2 = s3 = 0; } else { ctr[0] = ((UINT32 *)nonce)[0]; ctr[1] = ((UINT32 *)nonce)[1]; ctr[2] = ((UINT32 *)nonce)[2]; ctr[3] = 1; } CTR_INIT(&(c->ck), ctr, ctr + 3, tag, c->keylen); /* Hash associated data. */ if (alen) { b = alen >> 4; l = alen & 15; for (i=0;itable, adata); adata += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = adata[l]; GHB256B(c->table, tmp); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; } } /* Hash ciphertext. */ b = dlen >> 4; l = dlen & 15; for (i=0;ick), (&ctr[3]), out, c->keylen); ((UINT32 *)out)[0] ^= ((UINT32 *)data)[0]; ((UINT32 *)out)[1] ^= ((UINT32 *)data)[1]; ((UINT32 *)out)[2] ^= ((UINT32 *)data)[2]; ((UINT32 *)out)[3] ^= ((UINT32 *)data)[3]; GHB256B(c->table, out); data += GHASH_BLK_SZ; out += GHASH_BLK_SZ; } if (l) { CTR_ENCRYPT(&(c->ck), &ctr[3], ctr, c->keylen); for (i=0;itable, tmp); } GHB256B(c->table, (tmp + 4)); ((UINT32 *)tag)[0] ^= htonl(s0); ((UINT32 *)tag)[1] ^= htonl(s1); ((UINT32 *)tag)[2] ^= htonl(s2); ((UINT32 *)tag)[3] ^= htonl(s3); } MODIFIERS int gcm_decrypt_256b(gcm_ctx_256b *c, UINT8 *nonce, size_t nlen, UINT8 *ct, size_t ctlen, UINT8 *tag, size_t taglen, UINT8 *adata, size_t alen, UINT8 *pt) { UINT32 tmp[8] = {0, 0, 0, 0, htonl(alen >> 29), htonl(alen << 3), htonl(ctlen >> 29), htonl(ctlen << 3)}; UINT32 ctr[4]; UINT8 chksm[16]; register char *p; size_t b, l, i; register UINT32 t0, t1, t2, t3, tt; register UINT32 *entry; register UINT32 s0 = 0, s1 = 0, s2 = 0, s3 = 0; if (taglen > 16) taglen = 16; if (nlen != 12) { b = nlen >> 4; l = nlen & 15; while (b--) { GHB256B(c->table, nonce); nonce += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = nonce[l]; GHB256B(c->table, tmp); } tmp[0] = tmp[1] = 0; tmp[2] = htonl(nlen >> 29); tmp[3] = htonl(nlen << 3); GHB256B(c->table, tmp); ctr[0] = htonl(s0); ctr[1] = htonl(s1); ctr[2] = htonl(s2); ctr[3] = s3; tmp[0] = tmp[1] = tmp[2] = tmp[3] = s0 = s1 = s2 = s3 = 0; } else { ctr[0] = ((UINT32 *)nonce)[0]; ctr[1] = ((UINT32 *)nonce)[1]; ctr[2] = ((UINT32 *)nonce)[2]; ctr[3] = 1; } CTR_INIT(&(c->ck), ctr, ctr + 3, chksm, c->keylen); for (i=0;i> 4; l = alen & 15; for (i=0;itable, adata); adata += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = adata[l]; GHB256B(c->table, tmp); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; } } b = ctlen >> 4; l = ctlen & 15; p = (char*)ct; for (i=0;itable, p); p += GHASH_BLK_SZ; } if (l) { while (l--) ((UINT8 *)tmp)[l] = p[l]; GHB256B(c->table, tmp); } l = ctlen & 15; GHB256B(c->table, (tmp + 4)); ((UINT32 *)chksm)[0] ^= htonl(s0); ((UINT32 *)chksm)[1] ^= htonl(s1); ((UINT32 *)chksm)[2] ^= htonl(s2); ((UINT32 *)chksm)[3] ^= htonl(s3); for (i=taglen;i<16;i++) chksm[i] = 0; if (((UINT32 *)chksm)[0] || ((UINT32 *)chksm)[1] || ((UINT32 *)chksm)[2] || ((UINT32 *)chksm)[3]) return 0; for (i=0;ick), (&ctr[3]), pt, c->keylen); ((UINT32 *)pt)[0] ^= ((UINT32 *)ct)[0]; ((UINT32 *)pt)[1] ^= ((UINT32 *)ct)[1]; ((UINT32 *)pt)[2] ^= ((UINT32 *)ct)[2]; ((UINT32 *)pt)[3] ^= ((UINT32 *)ct)[3]; ct += GHASH_BLK_SZ; pt += GHASH_BLK_SZ; } if (l) { CTR_ENCRYPT(&(c->ck), &ctr[3], ctr, c->keylen); for (i=0;i> 24); (ct)[1] = (UINT8)((st) >> 16); (ct)[2] = (UINT8)((st) >> 8); (ct)[3] = (UINT8)(st); } #else #define GETUINT32(pt) (*(UINT32 *)(pt)) #define PUTUINT32(ct, st) (*(UINT32 *)(ct) = st) #endif #endif /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ int aes_enc_setup(UINT32 rk[], const UINT8 cipherKey[], int keyBits) { int i = 0; UINT32 temp; rk[0] = GETUINT32(cipherKey ); rk[1] = GETUINT32(cipherKey + 4); rk[2] = GETUINT32(cipherKey + 8); rk[3] = GETUINT32(cipherKey + 12); if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return 10; } rk += 4; } } rk[4] = GETUINT32(cipherKey + 16); rk[5] = GETUINT32(cipherKey + 20); if (keyBits == 192) { for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETUINT32(cipherKey + 24); rk[7] = GETUINT32(cipherKey + 28); if (keyBits == 256) { for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te4[(temp >> 24) ] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(temp ) & 0xff] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } void aes_ctr_first(UINT32 rk[64], UINT8 nonce[12], UINT32 *ctr, UINT8 ct[16], int klen) { UINT32 s0, s1, s2, s3, t0, t1, t2, t3; s0 = GETUINT32(nonce ) ^ rk[0]; s1 = GETUINT32(nonce + 4) ^ rk[1]; s2 = GETUINT32(nonce + 8) ^ rk[2]; s3 = *ctr ^ rk[3]; rk[60] = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ rk[ 4]; rk[61] = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; rk[62] = Te0[s2 >> 24] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; rk[63] = Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; t0 = rk[60] ^ Te3[s3 & 0xff]; t1 = rk[61] ^ Te2[(s3 >> 8) & 0xff]; t2 = rk[62] ^ Te1[(s3 >> 16) & 0xff]; t3 = rk[63] ^ Te0[s3 >> 24]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (klen > 128) { s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (klen == 256) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[56]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[57]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[58]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[59]; PUTUINT32(ct + 12, s3); } else { /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[48]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[49]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[50]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[51]; PUTUINT32(ct + 12, s3); } } else { /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[40]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[41]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[42]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[43]; PUTUINT32(ct + 12, s3); } } void aes_ctr(UINT32 rk[64], UINT32 ctr[1], UINT8 ct[16], int klen) { UINT32 s0, s1, s2, s3, t0, t1, t2, t3; s3 = ++ctr[0] ^ rk[3]; t0 = rk[60] ^ Te3[s3 & 0xff]; t1 = rk[61] ^ Te2[(s3 >> 8) & 0xff]; t2 = rk[62] ^ Te1[(s3 >> 16) & 0xff]; t3 = rk[63] ^ Te0[s3 >> 24]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (klen > 128) { s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (klen == 256) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[56]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[57]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[58]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[59]; PUTUINT32(ct + 12, s3); } else { /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[48]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[49]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[50]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[51]; PUTUINT32(ct + 12, s3); } } else { /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[40]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[41]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[42]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[43]; PUTUINT32(ct + 12, s3); } } void aes_enc(const UINT32 rk[], const UINT8 pt[16], UINT8 ct[16], int klen) { UINT32 s0, s1, s2, s3, t0, t1, t2, t3; s0 = GETUINT32(pt ) ^ rk[0]; s1 = GETUINT32(pt + 4) ^ rk[1]; s2 = GETUINT32(pt + 8) ^ rk[2]; s3 = GETUINT32(pt + 12) ^ rk[3]; t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (klen > 128) { s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (klen == 256) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[56]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[57]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[58]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[59]; PUTUINT32(ct + 12, s3); } else { /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[48]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[49]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[50]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[51]; PUTUINT32(ct + 12, s3); } } else { /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[40]; PUTUINT32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[41]; PUTUINT32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[42]; PUTUINT32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[43]; PUTUINT32(ct + 12, s3); } } anon-proxy-00.05.38+20081230/gcm/gcm.h0000644000175000017500000002304211122445202015373 0ustar daviddavid#ifndef _GCM_H #define _GCM_H #define MODIFIERS #define GHASH_BLK_SZ (16) /* GCM is a general-purpose encryption mode that uses a block cipher * to provide both data confidentiality and data integrity in a * single, easy to use construct. It provides these services in a * way that is provably secure to very high levels of assurance under * a standard assumption that the underlying block cipher exhibits * pseudo-random behavior (this assumption is widely believed to be * true, but will probably never be proven). * * GCM is a building block upon which one can easily build secure * channels. One need only add authentication, key agreement and * prevention against capture-replay attacks. * * GCM accepts several inputs: * - A key used to initialize the block cipher; * - Data to be encrypted or decrypted; * - A nonce, which is a value that should not be confidential * at all. The nonce is used in message security, much like an * initialization vector when using other encryption modes. The * only requirement for the nonce is that, given a particular * key, the nonce never be the same between two messages. * Generally, an always-incrementing message counter is * sufficient and can be used to protect against capture-replay * attacks as well. The integrity of the nonce is checked * implicitly when decrypting (but capture-replay is still * possible... one must still make sure the message counter * is both valid and larger than the last valid value); * - Additional data that one wishes to authenticate, but not * encrypt (such as header information that can be public). Note * that the length of a message is also authenticated implicitly * by this algorithm, so you do not need to include that with * the additional data. * * GCM in the abstract can work with any block cipher, but in * practice we expect it to be used primarily with AES. This * implementation is bound to block ciphers that have 128-bit block * sizes, such as AES. This implementation is an optimized version that * comes with its own AES implementation (a modification of the fast * reference code with some tweaks for speed). * * Under the hood, GCM uses the block cipher in CTR mode to produce a * stream of bytes used to encrypt both the plaintext and the message * authentication value. CTR mode is initialized using a function of * the nonce. That function is described in the GCM paper. * * To compute the message authentication value, we derive a "hash * key" and use a "universal hash function" to map the ciphertext to * a single 128-bit value. The universal hash function has * particular properties that manage to provide high assurance * levels. * * The universal hash function we use effectively consists of treating * both the key and the input block as a polynomial in the finite * field GF(2^128) and multiplying those polynomials. More * precicely, we'll treat our key k as a polynomial, and message * blocks m_1 through m_n as polynomials, and compute: * * m_1*k^n + m_2*k^(n-1) + ... + m_n*k * * Since these operations all happen in a finite field, the result * has a maximum size. We've chosen the field so that the range of * possible values has a one-to-one mapping to all of the ways you * can set 128 bits of memory. * * * As a reminder, a polynomial takes the form of: * a*x^n + b*x^(n-1) + ... + z*x^0. * * In the case of our hash function, the value of x is always * irrelevent and ignored. The coefficients can take the values 0 or 1. * * Because we're using a finite field, any math operations on our * polynomials are done modulo an "irreducible" polynomial, meaning * the polynomial has no other divisors (akin to a prime number). * The specific polynomial we use is: * * x^128 + x^7 + x^2 + x + 1 * * As a result, coefficients for x^128 and higher will always be 0. * * Our polynomials are then represented as a vector of 128 bits, * where each bit maps to a single coefficient. * * Because of the way finite fields work, and because coefficients * are either 0 or 1, adding two polynomials together can be * implemented efficiently by XOR-ing the two representations together. * * Multiplication is a bit trickier to understand and implement. The * strategies that we leverage all rely on a fundamental building * block, the multiplication of a polynomial by x. * * In general, if we have a polynomial and we multiply the whole * thing by x, we expect all of the coefficients to move to the left * one bit. For example: * * x^10 + x^7 + x^5 + x^2 + 1 * x = x^11 + x^8 + x^6 + x^3 + x * * Then, we need to do the modular reduction. As it turns out, this * can be done by ADDING the irreducible polynomial to the shifted * result. As noted above, this is simply an XOR operation. * * In our code, we call this operation mul_alpha (we name the * unimportant free variable alpha instead of x). This operation can * be used as the foundation by which we multiply together two * polynomials. * * Without going into the details of the derivation, it turns out we * can multiply two polynomials p and q using the following algorithm: * * - Start out with a resulting polynomial r, where r = 0 * - FOR N from 0 to 127: * - If the x^N term of p is 1, then add q*x^N to r. * * We can easily compute q*x^N by repeatedly using mul_alpha to * multiply q by x. One can work out a few examples longhand to see * that this does indeed give the same results as longhand * multiplication. * * One thing to note about this strategy that, if one of the * polynomials is fixed (which is the case in GCM, since one of the * polynomials in a multiplication operation will always be the * key... the other polynomial will be a block of input), then there * are some efficiencies at our disposal. * * First, we can precompute * all 128 values of q*x^N. This saves us * from performing 127 calls to mul_alpha every time we want to * process a single block. * * Second, we note that any time that, for a fixed power l, every * time the coefficient of x^l is 1 in the message block we're * processing, we always XOR in q*x^l. We can use this knowledge to * precompute the effects of several bits at once. * * For example, if the x^0 and x^1 terms of the message block are * both 1, then we'll always XOR in q*x and q. We can precompute * that value, and then look up the result of q*x XOR q based on the * value of those two bits. * * In practice, we will do this kind of precomputation and do it * either four bits at a time or eight bits at a time. If we do it * eight bits at a time, we will look at each byte of the message * block and precompute the 256 different possible effects the eight * corresponding coefficients can have on the final result. * * Processing 8 bits at a time makes things go quite quickly, since * we can look up a byte at a time. However, it requires 64K of * memory. Since this memory is key dependent, this may sometimes be * too much precomputation. Use gcm4k or gcm256 if this is an issue * (the later uses only about 300 bytes of state per key total). * */ /* When we do the modular reduction in mul_alpha, we add in the * polynomial x^128 + x^7 + x^2 + x + 1. The modular reduction only * needs to occur when the x^128 coefficient is 1, which means the * result for that coefficient will be 0 after the add (x^128 + x^128 * = 0, since addition is essentially XOR). * However, we still need to XOR in x^7 + x^2 + x + 1, and this * constant polynomial is represented by GHASH_ALPHA. */ #define GHASH_ALPHA 0xe1000000 #include "prp.h" #define GCM_J_LIMIT (0x100) #define GCM_LEFTMOST_BIT (0x80) #define GCM_NUM_BITS (0x08) #define GCM_I_LIMIT (16) typedef struct { UINT32 table[GCM_I_LIMIT][GCM_J_LIMIT][4]; KEY_SCHED ck; UINT32 keylen; } gcm_ctx_64k; typedef struct { UINT32 table[256][4]; KEY_SCHED ck; int keylen; } gcm_ctx_4k; typedef struct { UINT32 table[16][4]; KEY_SCHED ck; int keylen; } gcm_ctx_256b; MODIFIERS void gcm_init_64k(gcm_ctx_64k *c, UINT8 key[], size_t keylen); MODIFIERS void gcm_encrypt_64k(gcm_ctx_64k *c, UINT8 *nonce, size_t nlen, UINT8 *pt, size_t ptlen, UINT8 *adata, size_t alen, UINT8 *ct, UINT8 *tag); MODIFIERS int gcm_decrypt_64k(gcm_ctx_64k *c, UINT8 *nonce, size_t nlen, UINT8 *ct, size_t ctlen, UINT8 *tag, size_t taglen, UINT8 *adata, size_t alen, UINT8 *pt); MODIFIERS void gcm_destroy_64k(gcm_ctx_64k *c); MODIFIERS void gcm_init_4k(gcm_ctx_4k *c, UINT8 key[], size_t keylen); MODIFIERS void gcm_encrypt_4k(gcm_ctx_4k *c, UINT8 *nonce, size_t nlen, UINT8 *pt, size_t ptlen, UINT8 *adata, size_t alen, UINT8 *ct, UINT8 *tag); MODIFIERS int gcm_decrypt_4k(gcm_ctx_4k *c, UINT8 *nonce, size_t nlen, UINT8 *ct, size_t ctlen, UINT8 *tag, size_t taglen, UINT8 *adata, size_t alen, UINT8 *pt); MODIFIERS void gcm_destroy_4k(gcm_ctx_4k *c); MODIFIERS void gcm_init_256b(gcm_ctx_256b *c, UINT8 key[], size_t keylen); MODIFIERS void gcm_encrypt_256b(gcm_ctx_256b *c, UINT8 *nonce, size_t nlen, UINT8 *pt, size_t ptlen, UINT8 *adata, size_t alen, UINT8 *ct, UINT8 *tag); MODIFIERS int gcm_decrypt_256b(gcm_ctx_256b *c, UINT8 *nonce, size_t nlen, UINT8 *ct, size_t ctlen, UINT8 *tag, size_t taglen, UINT8 *adata, size_t alen, UINT8 *pt); MODIFIERS void gcm_destroy_256b(gcm_ctx_256b *c); #endif /* _GCM_H */ anon-proxy-00.05.38+20081230/gcm/prp.h0000644000175000017500000000275411122445202015435 0ustar daviddavid/** * prp.h * * Optimised ANSI C AES code modified from reference code. Decrypt * routine is removed, and the code is optimized for GCM's awesome * brand of counter mode, where only the lower 32 bits change. This * means we can skip nearly a whole round per block cipher invocation. */ #ifndef __PRP_H #define __PRP_H #define MAXKC (256/32) #define MAXKB (256/8) #define MAXNR 14 /* This implementation operates on fixed-size types. We assume that * one has a 64-bit int type. While few machines still provide such * a type natively, most compilers will automatically emulate a * 64-bit type when there isn't a native one available. */ typedef UINT32 AES_CTR_CTX[64]; int aes_enc_setup(UINT32 rk[], const UINT8 cipherKey[], int keyBits); void aes_ctr_first(UINT32 rk[64], UINT8 nonce[12], UINT32 *ctr, UINT8 ct[16], int keyBits); void aes_enc(const UINT32 rk[], const UINT8 pt[16], UINT8 ct[16], int keyBits); void aes_ctr(UINT32 rk[64], UINT32 ctr[1], UINT8 ct[16], int keyBits); #define KEY_SCHED AES_CTR_CTX #define ENCRYPT_INIT(sched, key, keylen) aes_enc_setup((UINT32 *)(sched), key, keylen) #define CTR_INIT(sched, nonce, ctr, out, keylen) aes_ctr_first((UINT32 *)(sched), (UINT8 *)(nonce), (UINT32 *)(ctr), (UINT8 *)(out), keylen) #define CTR_ENCRYPT(sched, ctr, out, keylen) aes_ctr((UINT32 *)(sched), (UINT32 *)(ctr), (UINT8 *)(out), keylen) #define DO_ENCRYPT(sched, in, out, keylen) aes_enc((UINT32 *)(sched), (UINT8 *)(in), (UINT8 *)(out), keylen) #endif /* __PRP_H */ anon-proxy-00.05.38+20081230/CASingleSocketGroup.hpp0000644000175000017500000001350011035407105020233 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CASINGLESOCKETGROUP__ #define __CASINGLESOCKETGROUP__ #ifdef _DEBUG #include "CAMsg.hpp" #endif /** Not thread safe!*/ #if !defined(HAVE_POLL)&&!defined(HAVE_EPOLL) #include "CASocketGroup.hpp" class CASingleSocketGroup:public CASocketGroup { public: CASingleSocketGroup(bool bWrite):CASocketGroup(bWrite) { } static SINT32 select_once(CASocket& s,bool bWrite,UINT32 time_ms) { fd_set fdset; FD_ZERO(&fdset); #pragma warning( push ) #pragma warning( disable : 4127 ) //Disable: Bedingter Ausdruck ist konstant FD_SET((SOCKET)s,&fdset); #pragma warning( pop ) SINT32 ret; timeval ti; ti.tv_sec=0; ti.tv_usec=time_ms*1000; if(bWrite) ret=::select(1,NULL,&fdset,NULL,&ti); else ret=::select(1,&fdset,NULL,NULL,&ti); if(ret>0) return ret; else if(ret==0) return E_TIMEDOUT; return E_UNKNOWN; } }; #else #include "CAMuxSocket.hpp" #ifdef HAVE_POLL class CASingleSocketGroup { public: CASingleSocketGroup(bool bWrite) { m_pollfd=new struct pollfd; setPoolForWrite(bWrite); } ~CASingleSocketGroup() { delete m_pollfd; m_pollfd = NULL; } SINT32 add(CASocket&s) { m_pollfd->fd=(SOCKET)s; return E_SUCCESS; } SINT32 add(CAMuxSocket&s) { m_pollfd->fd=(SOCKET)s; return E_SUCCESS; } SINT32 setPoolForWrite(bool bWrite) { if(bWrite) m_pollfd->events=POLLOUT; else m_pollfd->events=POLLIN; return E_SUCCESS; } SINT32 select() { return ::poll(m_pollfd,1,-1); } /** Waits for "events" on the socket. * @param time_ms time in milli seconds to wait * @return E_TIMEDOUT if after time_ms milli seconds no event occured * @return E_UNKNOWN if an error occured * @return 1 if an event occured */ SINT32 select(UINT32 time_ms) { SINT32 ret=::poll(m_pollfd,1,time_ms); if(ret==1) return ret; else if(ret==0) { return E_TIMEDOUT; } #ifdef _DEBUG ret=GET_NET_ERROR; CAMsg::printMsg(LOG_DEBUG,"SocketGroup Select-Fehler: %i\n",ret); #endif return E_UNKNOWN; } static SINT32 select_once(CASocket& s,bool bWrite,UINT32 time_ms) { struct pollfd pollfd; if(bWrite) pollfd.events=POLLOUT; else pollfd.events=POLLIN; pollfd.fd=(SOCKET)s; SINT32 ret=::poll(&pollfd,1,time_ms); if(ret==1) return ret; else if(ret==0) return E_TIMEDOUT; return E_UNKNOWN; } private: struct pollfd* m_pollfd; }; #elif defined(HAVE_EPOLL) class CASingleSocketGroup { public: CASingleSocketGroup(bool bWrite) { m_hEPFD=epoll_create(1); setPoolForWrite(bWrite); } ~CASingleSocketGroup() { close(hEPFD); } SINT32 add(CAMuxSocket&s) { if(epoll_ctl(m_hEPFD,EPOLL_CTL_ADD,(SOCKET)s,&m_pollAdd)!=0) return E_UNKNOWN; return E_SUCCESS; } SINT32 add(CAMuxSocket&s) { if(epoll_ctl(m_hEPFD,EPOLL_CTL_ADD,s.getSocket(),&m_pollAdd)!=0) return E_UNKNOWN; return E_SUCCESS; } SINT32 setPoolForWrite(bool bWrite) { if(bWrite) m_pollAdd->events=POLLOUT|POLLERR|POLLHUP; else m_pollfd->events=POLLIN|POLLERR|POLLHUP; return E_SUCCESS; } SINT32 select() { return ::epoll_wait(m_hEPFD,&m_Events,1,-1); } SINT32 select(UINT32 time_ms) { SINT32 ret=::epoll_wait(m_hEPFD,&m_Events,1,time_ms); if(ret==1) return ret; else if(ret==0) { return E_TIMEDOUT; } #ifdef _DEBUG ret=GET_NET_ERROR; CAMsg::printMsg(LOG_DEBUG,"SocketGroup Select-Fehler: %i\n",ret); #endif return E_UNKNOWN; } static SINT32 select_once(CASocket& s,bool bWrite,UINT32 time_ms) { struct epool_events events; if(bWrite) events.events=POLLOUT|POLLERR|POLLHUP; else events.events=POLLIN|POLLERR|POLLHUP; epoll_ctl(m_hEPFD,EPOLL_CTL_ADD,(SOCKET)s,&events); SINT32 ret=::epoll_wait(m_hEPFD,&events,1,time_ms); if(ret==1) return ret; else if(ret==0) { return E_TIMEDOUT; } return E_UNKNOWN; } private: struct epool_events m_epollAdd; struct epool_events m_Events; SINT32 m_hEPFD; }; #endif #endif #endif anon-proxy-00.05.38+20081230/CAAccountingSettleThread.cpp0000644000175000017500000004016311123430142021222 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #ifdef PAYMENT #include "CAAccountingSettleThread.hpp" #include "CAAccountingBIInterface.hpp" #include "CAAccountingDBInterface.hpp" #include "CACmdLnOptions.hpp" #include "CAAccountingInstance.hpp" #include "CASocketAddrINet.hpp" #include "CAXMLCostConfirmation.hpp" #include "CAXMLErrorMessage.hpp" #include "Hashtable.hpp" extern CACmdLnOptions* pglobalOptions; CAAccountingSettleThread::CAAccountingSettleThread(Hashtable* a_accountingHashtable, UINT8* currentCascade)/*, CAAccountingBIInterface *pPiInterface, CAAccountingDBInterface *pDbInterface)*/ { // launch AI thread m_pThread = new CAThread((UINT8*)"Accounting Settle Thread"); m_settleCascade = currentCascade; //m_pPiInterface = pPiInterface; //m_pDbInterface = pDbInterface; m_pThread->setMainLoop( mainLoop ); CAMsg::printMsg(LOG_DEBUG, "Now launching Accounting SettleThread...\n"); m_bRun=true; m_accountingHashtable = a_accountingHashtable; m_pCondition = new CAConditionVariable; m_pThread->start(this); } CAAccountingSettleThread::~CAAccountingSettleThread() { m_bRun=false; if(m_pThread != NULL) { settle(); m_pThread->join(); delete m_pThread; m_pThread = NULL; } if(m_pCondition != NULL) { delete m_pCondition; m_pCondition = NULL; } } void CAAccountingSettleThread::settle() { m_pCondition->lock(); //m_bSleep = false; m_pCondition->signal(); m_pCondition->unlock(); } /** * The main loop. Sleeps for a few minutes, then contacts the BI to settle CCs, * then sleeps again */ THREAD_RETURN CAAccountingSettleThread::mainLoop(void * pParam) { INIT_STACK; BEGIN_STACK("CAAccountingSettleThread::mainLoop"); UINT32 settlement_status; UINT32 sleepInterval = pglobalOptions->getPaymentSettleInterval(); CAAccountingSettleThread* m_pAccountingSettleThread=(CAAccountingSettleThread*)pParam; /*CAAccountingBIInterface *biConn = new CAAccountingBIInterface(); CAAccountingDBInterface dbConn; CAXMLErrorMessage * pErrMsg; CAXMLCostConfirmation * pCC; UINT32 sleepInterval; CAQueue q; UINT32 size; //CASocketAddrINet biAddr; SettleEntry* entry; SettleEntry* nextEntry; bool bPICommunicationError; CAMsg::printMsg(LOG_DEBUG, "Accounting SettleThread is running...\n"); m_pAccountingSettleThread->m_bSleep = false; CAXMLBI* pBI = pglobalOptions->getBI(); if(pBI==NULL) { CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread; Uuupss.. No BI given --> dying!\n"); THREAD_RETURN_ERROR; } //biAddr.setAddr(pBI->getHostName(), (UINT16)pBI->getPortNumber()); biConn->setPIServerConfiguration(pBI);*/ CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread: Start loop...\n"); while(m_pAccountingSettleThread->m_bRun) { m_pAccountingSettleThread->m_pCondition->lock(); m_pAccountingSettleThread->m_pCondition->wait(sleepInterval * 1000); m_pAccountingSettleThread->m_pCondition->unlock(); settlement_status = CAAccountingInstance::settlementTransaction(); if(settlement_status != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "AccountingSettleThread: Settlement transaction failed\n"); } } //return THREAD_RETURN_SUCCESS; /*while(0) { SAVE_STACK("CAAccountingSettleThread::mainLoop", "Loop"); m_pAccountingSettleThread->m_pCondition->lock(); if (m_pAccountingSettleThread->m_bSleep) { m_pAccountingSettleThread->m_bSleep = false; #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Accounting SettleThread going to sleep...\n"); #endif #ifdef DEBUG UINT64 currentMillis; UINT8 tmpStrCurrentMillis[50]; getcurrentTimeMillis(currentMillis); print64(tmpStrCurrentMillis,currentMillis); CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread: Wait start: %s\n", tmpStrCurrentMillis); #endif m_pAccountingSettleThread->m_pCondition->wait(sleepInterval * 1000); #ifdef DEBUG getcurrentTimeMillis(currentMillis); print64(tmpStrCurrentMillis,currentMillis); CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread: Wait stop: %s\n", tmpStrCurrentMillis); #endif //sSleep((UINT16)sleepInterval); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Accounting SettleThread Waking up...\n"); #endif if(!m_pAccountingSettleThread->m_bRun) { CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread: Leaving run loop\n"); break; } } m_pAccountingSettleThread->m_pCondition->unlock(); if(!dbConn.isDBConnected() && dbConn.initDBConnection()!=E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "SettleThread could not connect to Database. Retrying later...\n"); m_pAccountingSettleThread->m_bSleep = true; continue; } #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Accounting SettleThread: DB connections established!\n"); #endif dbConn.getUnsettledCostConfirmations(q, m_pAccountingSettleThread->m_settleCascade); if (q.isEmpty()) { CAMsg::printMsg(LOG_DEBUG, "Accounting SettleThread: finished gettings CCs, found no CCs to settle\n"); m_pAccountingSettleThread->m_bSleep = true; continue; } else { UINT32 qSize = q.getSize(); UINT32 nrOfCCs = qSize / sizeof(pCC); CAMsg::printMsg(LOG_DEBUG, "SettleThread: finished gettings CCs, found %u cost confirmations to settle\n",nrOfCCs); } entry = NULL; bPICommunicationError = false; while(!q.isEmpty() && m_pAccountingSettleThread->m_bRun) { SAVE_STACK("CAAccountingSettleThread::mainLoop", "Settling"); // get the next CC from the queue size = sizeof(pCC); if(q.get((UINT8*)(&pCC), &size)!=E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "SettleThread: could not get next item from queue\n"); q.clean(); break; } if (!pCC) { CAMsg::printMsg(LOG_CRIT, "CAAccountingSettleThread: Cost confirmation is NULL!\n"); continue; } //#ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "Settle Thread: Connecting to payment instance...\n"); //#endif if(biConn->initBIConnection() != E_SUCCESS) { if (!bPICommunicationError) { CAMsg::printMsg(LOG_DEBUG, "SettleThread: could not connect to BI. Retrying later...\n"); } //q.clean(); pErrMsg = NULL; // continue in order to tell AUTH_WAITING_FOR_FIRST_SETTLED_CC for all accounts bPICommunicationError = true; biConn->terminateBIConnection(); // make sure the socket is closed } else { #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "SettleThread: successfully connected to payment instance"); #endif bPICommunicationError = false; pErrMsg = biConn->settle( *pCC ); biConn->terminateBIConnection(); CAMsg::printMsg(LOG_DEBUG, "CAAccountingSettleThread: settle done!\n"); } bool bDeleteCC = false; UINT32 authFlags = 0; UINT32 authRemoveFlags = 0; UINT64 confirmedBytes = 0; UINT64 diffBytes = 0; // check returncode if(pErrMsg == NULL) //no returncode -> connection error { m_pAccountingSettleThread->m_bSleep = true; authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; // no fault of the client CAMsg::printMsg(LOG_ERR, "SettleThread: Communication with BI failed!\n"); } else if(pErrMsg->getErrorCode() != pErrMsg->ERR_OK) //BI reported error { CAMsg::printMsg(LOG_ERR, "CAAccountingSettleThread: BI reported error no. %d (%s)\n", pErrMsg->getErrorCode(), pErrMsg->getDescription() ); if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_KEY_NOT_FOUND) { authFlags |= AUTH_INVALID_ACCOUNT; //dbConn.storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_KEY_NOT_FOUND); bDeleteCC = true; } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_ACCOUNT_EMPTY) { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; authFlags |= AUTH_ACCOUNT_EMPTY; UINT64* msgConfirmedBytes = (UINT64*)pErrMsg->getMessageObject(); if (msgConfirmedBytes) { confirmedBytes = *msgConfirmedBytes; if (confirmedBytes < pCC->getTransferredBytes()) { diffBytes = pCC->getTransferredBytes() - confirmedBytes; } UINT8 tmp[32]; print64(tmp, confirmedBytes); CAMsg::printMsg(LOG_ERR, "CAAccountingSettleThread: Received %s confirmed bytes!\n", tmp); } dbConn.storeAccountStatus(pCC->getAccountNumber(), CAXMLErrorMessage::ERR_ACCOUNT_EMPTY, pErrMsg->getExpTimeString()); dbConn.markAsSettled(pCC->getAccountNumber(), m_pAccountingSettleThread->m_settleCascade, pCC->getTransferredBytes()); } *//* else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_INVALID_PRICE_CERT) { // this should never happen; the price certs in this CC do not fit to the ones of the cascade // bDeleteCC = true; }*/ /*else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_OUTDATED_CC) { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; // this is a Mix not a client error //get attached CC from error message CAXMLCostConfirmation* attachedCC = (CAXMLCostConfirmation*) pErrMsg->getMessageObject(); if (attachedCC) { authFlags |= AUTH_OUTDATED_CC; CAMsg::printMsg(LOG_DEBUG, "SettleThread: tried outdated CC, received last valid CC back\n"); //store it in DB if (dbConn.storeCostConfirmation(*attachedCC, m_pAccountingSettleThread->m_settleCascade) == E_SUCCESS) { if (dbConn.markAsSettled(attachedCC->getAccountNumber(), m_pAccountingSettleThread->m_settleCascade, attachedCC->getTransferredBytes()) != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "SettleThread: Could not mark last valid CC as settled." "Maybe a new CC has been added meanwhile?\n"); } } else { CAMsg::printMsg(LOG_ERR, "SettleThread: storing last valid CC in db failed!\n"); } // set the confirmed bytes to the value of the CC got from the PI confirmedBytes = attachedCC->getTransferredBytes(); } else { CAMsg::printMsg(LOG_DEBUG, "SettleThread: Did not receive last valid CC - maybe old Payment instance?\n"); } } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_BLOCKED) { authFlags |= AUTH_BLOCKED; bDeleteCC = true; } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_DATABASE_ERROR) { //authFlags |= AUTH_DATABASE; // the user is not responsible for this! authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; m_pAccountingSettleThread->m_bSleep = true; } else if (pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR || pErrMsg->getErrorCode() == CAXMLErrorMessage::ERR_SUCCESS_BUT_WITH_ERRORS) { // kick out the user and store the CC authFlags |= AUTH_UNKNOWN; m_pAccountingSettleThread->m_bSleep = true; } else { // an unknown error leads to user kickout CAMsg::printMsg(LOG_DEBUG, "SettleThread: Setting unknown kickout error no. %d.\n", pErrMsg->getErrorCode()); authFlags |= AUTH_UNKNOWN; bDeleteCC = true; } if (bDeleteCC) { //delete costconfirmation to avoid trying to settle an unusable CC again and again if(dbConn.deleteCC(pCC->getAccountNumber(), m_pAccountingSettleThread->m_settleCascade) == E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "SettleThread: unusable cost confirmation was deleted\n"); } else { CAMsg::printMsg(LOG_ERR, "SettleThread: cost confirmation is unusable, but could not delete it from database\n"); } } } else //settling was OK, so mark account as settled { authRemoveFlags |= AUTH_WAITING_FOR_FIRST_SETTLED_CC; if (dbConn.markAsSettled(pCC->getAccountNumber(), m_pAccountingSettleThread->m_settleCascade, pCC->getTransferredBytes()) != E_SUCCESS) { CAMsg::printMsg(LOG_ERR, "SettleThread: Could not mark CC as settled. Maybe a new CC has been added meanwhile?\n"); } } if (authFlags || authRemoveFlags) { nextEntry = new SettleEntry; nextEntry->accountNumber = pCC->getAccountNumber(); nextEntry->authFlags = authFlags; nextEntry->authRemoveFlags = authRemoveFlags; nextEntry->confirmedBytes = confirmedBytes; nextEntry->diffBytes = diffBytes; nextEntry->nextEntry = entry; entry = nextEntry; } if (pCC != NULL) { delete pCC; pCC = NULL; } if (pErrMsg != NULL) { delete pErrMsg; pErrMsg = NULL; } }*/ /* * Now alter the hashtable entries if needed. This blocks communication with JAP clients * and should therefore be done as quickly as possible. */ /*if (entry) { m_pAccountingSettleThread->m_accountingHashtable->getMutex()->lock(); while (entry) { AccountLoginHashEntry* loginEntry = (AccountLoginHashEntry*) (m_pAccountingSettleThread->m_accountingHashtable->getValue(&(entry->accountNumber))); if (loginEntry) { // the user is currently logged in loginEntry->authFlags |= entry->authFlags; loginEntry->authRemoveFlags |= entry->authRemoveFlags; if (entry->confirmedBytes) { loginEntry->confirmedBytes = entry->confirmedBytes; } } else if (entry->authFlags & (AUTH_INVALID_ACCOUNT | AUTH_UNKNOWN)) { // user is currently not logged in; delete prepaid bytes in DB dbConn.storePrepaidAmount( entry->accountNumber, 0, m_pAccountingSettleThread->m_settleCascade); } else if (entry->diffBytes) { // user is currently not logged in; set correct prepaid bytes in DB SINT32 prepaidBytes = dbConn.getPrepaidAmount(entry->accountNumber, m_pAccountingSettleThread->m_settleCascade, true); if (prepaidBytes > 0) { if (entry->diffBytes >= (UINT32)prepaidBytes) { prepaidBytes = 0; } else { prepaidBytes -= entry->diffBytes; } dbConn.storePrepaidAmount( entry->accountNumber, prepaidBytes, m_pAccountingSettleThread->m_settleCascade); } } nextEntry = entry->nextEntry; delete entry; entry = nextEntry; } m_pAccountingSettleThread->m_accountingHashtable->getMutex()->unlock(); } }//main while run loop*/ FINISH_STACK("CAAccountingSettleThread::mainLoop"); CAMsg::printMsg(LOG_DEBUG, "AccountingSettleThread: Exiting run loop!\n"); /*dbConn.terminateDBConnection(); delete biConn; biConn = NULL;*/ THREAD_RETURN_SUCCESS; } #endif //PAYMENT anon-proxy-00.05.38+20081230/CAConditionVariable.hpp0000644000175000017500000001356211035407103020226 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CACONVAR__ #define __CACONVAR__ #ifndef ONLY_LOCAL_PROXY #include "CAMutex.hpp" #include "CAUtil.hpp" #include "CASemaphore.hpp" class CAConditionVariable:public CAMutex { public: CAConditionVariable() { #ifdef HAVE_PTHREAD_CV m_pCondVar=new pthread_cond_t; pthread_cond_init(m_pCondVar,NULL); #else m_pMutex=new CAMutex(); m_pSemaphore=new CASemaphore(0); m_iSleepers=0; #endif } ~CAConditionVariable() { #ifdef HAVE_PTHREAD_CV pthread_cond_destroy(m_pCondVar); delete m_pCondVar; m_pCondVar = NULL; #else delete m_pMutex; m_pMutex = NULL; delete m_pSemaphore; m_pSemaphore = NULL; #endif } /** Waits for a signal or for a timeout. * Note: lock() must be called before wait() and unlock() * must be called if proccessing ends. * @retval E_SUCCESS if signaled * @retval E_UNKNOWN if an error occured */ SINT32 wait() { #ifdef HAVE_PTHREAD_CV if(pthread_cond_wait(m_pCondVar,m_pMutex)==0) return E_SUCCESS; return E_UNKNOWN; #else m_pMutex->lock(); unlock(); // Release the lock that is associated with our cv m_iSleepers++; m_pMutex->unlock(); m_pSemaphore->down(); return lock(); #endif } /** Very ugly shortly to be deleted, uncommented function! */ SINT32 wait(CAMutex& oMutex) { #ifdef HAVE_PTHREAD_CV if(pthread_cond_wait(m_pCondVar,oMutex.m_pMutex)==0) return E_SUCCESS; return E_UNKNOWN; #else m_pMutex->lock(); oMutex.unlock(); // Release the lock that is associated with our cv m_iSleepers++; m_pMutex->unlock(); m_pSemaphore->down(); return oMutex.lock(); #endif } /** Very ugly shortly to be deleted, uncommented function! */ SINT32 wait(CAMutex* pMutex) { #ifdef HAVE_PTHREAD_CV if(pthread_cond_wait(m_pCondVar,pMutex->m_pMutex)==0) return E_SUCCESS; return E_UNKNOWN; #else m_pMutex->lock(); pMutex->unlock(); // Release the lock that is associated with our cv m_iSleepers++; m_pMutex->unlock(); m_pSemaphore->down(); return pMutex->lock(); #endif } /** Waits for a signal or for a timeout. * Note: lock() must be called before wait() and unlock() * must be called if proccessing ends. * @param msTimeout timout value in millis seconds * @retval E_SUCCESS if signaled * @retval E_TIMEDOUT if timout was reached * @retval E_UNKNOWN if an error occured */ SINT32 wait(UINT32 msTimeout) { #ifdef HAVE_PTHREAD_CV timespec to; getcurrentTime(to); to.tv_nsec+=(msTimeout%1000)*1000000; to.tv_sec+=msTimeout/1000; if(to.tv_nsec>999999999) { to.tv_sec++; to.tv_nsec-=1000000000; } int ret=pthread_cond_timedwait(m_pCondVar,m_pMutex,&to); if(ret==0) return E_SUCCESS; else if(ret==ETIMEDOUT) return E_TIMEDOUT; return E_UNKNOWN; #else ///@todo add something better here.... return wait(); #endif } /** Signals this object. One of the threads waiting on this object will awake. * Note: lock() must be called before signal() and unlock() * must be called if proccessing ends. */ SINT32 signal() { #ifdef HAVE_PTHREAD_CV if(pthread_cond_signal(m_pCondVar)==0) return E_SUCCESS; return E_UNKNOWN; #else m_pMutex->lock(); if( m_iSleepers > 0 ) { m_pSemaphore->up(); m_iSleepers--; } return m_pMutex->unlock(); #endif } /** Signals this object. All threads waiting on this object will awake. * Note: lock() must be called before broadcast() and unlock() * must be called if proccessing ends. */ SINT32 broadcast() { #ifdef HAVE_PTHREAD_CV if(pthread_cond_broadcast(m_pCondVar)==0) return E_SUCCESS; return E_UNKNOWN; #else m_pMutex->lock(); while( m_iSleepers > 0 ) { m_pSemaphore->up(); m_iSleepers--; } return m_pMutex->unlock(); #endif } private: #ifdef HAVE_PTHREAD_CV pthread_cond_t* m_pCondVar; #else CAMutex* m_pMutex; CASemaphore* m_pSemaphore; UINT32 m_iSleepers; #endif }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/CABase64.hpp0000644000175000017500000000327310016604654015664 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ class CABase64 { public: static SINT32 decode(const UINT8* in,UINT32 len,UINT8* out,UINT32* outlen); static SINT32 encode(const UINT8* in,UINT32 len,UINT8* out,UINT32* outlen); }; anon-proxy-00.05.38+20081230/FlashMix/0000755000175000017500000000000011126517127015432 5ustar daviddavidanon-proxy-00.05.38+20081230/FlashMix/CAMainThread.cpp0000644000175000017500000000471510162311576020364 0ustar daviddavid#include "../StdAfx.h" #include "CAMainThread.hpp" CAMainThread::CAMainThread(UINT32 a_uPort, THREAD_MAIN_TYP a_fncHandleRequest) { m_uPort = a_uPort; m_fncHandleRequest = a_fncHandleRequest; m_bRun = false; if ((m_pThread = new CAThread()) != NULL) m_pThread->setMainLoop(thread); } CAMainThread::~CAMainThread() { stop(); join(); delete m_pThread; } SINT32 CAMainThread::start() { SINT32 result = E_SUCCESS; m_bRun = true; result = m_pThread->start(this); return result; } SINT32 CAMainThread::stop() { SINT32 result = E_SUCCESS; CASocket* pSocket = new CASocket(); CASocketAddrINet* pAddr = new CASocketAddrINet(); m_bRun = false; if ((pSocket == NULL) || (pAddr == NULL)) result = E_UNKNOWN; else result = pSocket->create(); if (result == E_SUCCESS) result = pAddr->setAddr((UINT8*)"127.0.0.1", m_uPort); if (result == E_SUCCESS) pSocket->connect(*pAddr, 1, 1); if (pSocket != NULL) pSocket->close(); delete pSocket; delete pAddr; return result; } SINT32 CAMainThread::join() { return m_pThread->join(); } THREAD_RETURN CAMainThread::thread(void* a_pThis) { SINT32 result = E_SUCCESS; CAMainThread* ths = (CAMainThread*)a_pThis; CASocket* pSocket = new CASocket(); if (pSocket == NULL) result = E_UNKNOWN; else result = pSocket->create(); if (result == E_SUCCESS) result = pSocket->listen(ths->m_uPort); CAMsg::printMsg(LOG_DEBUG, "MainThread startet\n"); while ((ths->m_bRun) && (result == E_SUCCESS)) { CASocket* pClient = new CASocket(); if (pClient == NULL) result = E_UNKNOWN; else result = pSocket->accept(*pClient); if ((ths->m_bRun) && (result == E_SUCCESS)) { pthread_t pThread; UINT32* req = new UINT32[2]; if (req == NULL) result = E_UNKNOWN; else { req[0] = (UINT32)ths; req[1] = (UINT32)pClient; } if (result == E_SUCCESS) pthread_create(&pThread, NULL, ths->m_fncHandleRequest, req); } else { if (pClient != NULL) pClient->close(); delete pClient; } } CAMsg::printMsg(LOG_DEBUG, "MainThread finished\n"); if (pSocket != NULL) pSocket->close(); delete pSocket; THREAD_RETURN_SUCCESS; } anon-proxy-00.05.38+20081230/FlashMix/BulletinBoard.cpp0000644000175000017500000000407010676452766020705 0ustar daviddavid#include "../StdAfx.h" #include "../CACmdLnOptions.hpp" #include "../CAMsg.hpp" #include "elgamal.hpp" #include "CABNSend.hpp" #include "FlashMixGlobal.hpp" #include "CABulletinBoard.hpp" #ifdef __BORLANDC__ #pragma argsused #endif #include CACmdLnOptions* pglobalOptions; unsigned int port = 16000; unsigned int keylength = 1024; unsigned int mix_n = 3; unsigned int mix_p = 2; unsigned int mix_d = 2; unsigned int msg = 1024; void readParam(int argc, char* argv[]) { for (int i = 0; i < argc; i++) { if (strstr(argv[i], "--port=") == argv[i]) port = atoi(argv[i] + 7); else if (strstr(argv[i], "--keylength=") == argv[i]) keylength = atoi(argv[i] + 12); else if (strstr(argv[i], "--mix-d=") == argv[i]) mix_d = atoi(argv[i] + 8); else if (strstr(argv[i], "--mix-p=") == argv[i]) mix_p = atoi(argv[i] + 8); else if (strstr(argv[i], "--mix-n=") == argv[i]) mix_n = atoi(argv[i] + 8); else if (strstr(argv[i], "--msg=") == argv[i]) msg = atoi(argv[i] + 6); else if (strstr(argv[i], "/port=") == argv[i]) port = atoi(argv[i] + 6); else if (strstr(argv[i], "/keylength=") == argv[i]) keylength = atoi(argv[i] + 11); else if (strstr(argv[i], "/mix-d=") == argv[i]) mix_d = atoi(argv[i] + 7); else if (strstr(argv[i], "/mix-p=") == argv[i]) mix_p = atoi(argv[i] + 7); else if (strstr(argv[i], "/mix-n=") == argv[i]) mix_n = atoi(argv[i] + 7); else if (strstr(argv[i], "/msg=") == argv[i]) msg = atoi(argv[i] + 5); } } int main( int argc, char * argv[] ) { #ifdef _WIN32 int err = 0; WSADATA wsadata; err = WSAStartup(0x0202, &wsadata); #endif CASocketAddrINet::init(); CAMsg::init(); readParam(argc, argv); CABulletinBoard* bb = new CABulletinBoard(port, keylength, mix_n, mix_p, mix_d, msg); bb->init(); bb->start(); char c; std::cin >> c; delete bb; return 0; } anon-proxy-00.05.38+20081230/FlashMix/CAMainThread.hpp0000644000175000017500000000113110162311576020356 0ustar daviddavid#ifndef __CAMAINTHREAD__ #define __CAMAINTHREAD__ #include "../CAThread.hpp" #include "../CASocket.hpp" #include "../CASocketAddrINet.hpp" #include "../CAMsg.hpp" class CAMainThread { public: CAMainThread(UINT32 a_uPort, THREAD_MAIN_TYP a_fncHandleRequest); ~CAMainThread(); SINT32 start(); SINT32 stop(); SINT32 join(); protected: UINT32 m_uPort; private: bool m_bRun; CAThread* m_pThread; THREAD_MAIN_TYP m_fncHandleRequest; static THREAD_RETURN thread(void* a_pThis); }; #endif // __CAMAINTHREAD__ anon-proxy-00.05.38+20081230/FlashMix/FlashMixGlobal.cpp0000644000175000017500000003402010162311576020770 0ustar daviddavid#include "../StdAfx.h" #include "FlashMixGlobal.hpp" MIXDATA* MIXDATA_new() { MIXDATA* ret; ret = (MIXDATA*)OPENSSL_malloc(sizeof(MIXDATA)); if (ret == NULL) return NULL; ret->cIP = NULL; ret->elEncKey = NULL; ret->elSignKey = NULL; return ret; } void MIXDATA_free(MIXDATA* a_pMIXData) { if (a_pMIXData == NULL) return; ELGAMAL_free(a_pMIXData->elEncKey); ELGAMAL_free(a_pMIXData->elSignKey); delete[] a_pMIXData->cIP; OPENSSL_free(a_pMIXData); a_pMIXData = NULL; } SINT32 initBN(BIGNUM** r_bn, UINT32 a_uSetWord) { if (r_bn == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; if (*r_bn != NULL) BN_clear_free(*r_bn); if ((*r_bn = BN_new()) == NULL) result = E_UNKNOWN; else { BN_init(*r_bn); if (BN_set_word(*r_bn, a_uSetWord) == 0) result = E_UNKNOWN; } if (result != E_SUCCESS) { if (*r_bn != NULL) BN_free(*r_bn); *r_bn = NULL; } return result; } SINT32 initBN(SINT32& ar_sResult, BIGNUM** r_bn, UINT32 a_uSetWord) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initBN(r_bn, a_uSetWord); return ar_sResult; } SINT32 initBNRand(BIGNUM** r_bn, UINT32 a_uBitLength) { if (r_bn == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; initBN(result, r_bn); if (result == E_SUCCESS) if (BN_rand(*r_bn, a_uBitLength, 1, 1) == 0) result = E_UNKNOWN; if (result != E_SUCCESS) { if (*r_bn != NULL) BN_free(*r_bn); *r_bn = NULL; } return result; } SINT32 initBNRand(SINT32& ar_sResult, BIGNUM** r_bn, UINT32 a_uBitLength) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initBNRand(r_bn, a_uBitLength); return ar_sResult; } void clearBN(BIGNUM** a_bn) { if (*a_bn != NULL) BN_clear_free(*a_bn); *a_bn = NULL; } SINT32 initCTX(BN_CTX** r_ctx) { if (r_ctx == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; if (*r_ctx != NULL) BN_CTX_free(*r_ctx); if ((*r_ctx = BN_CTX_new()) == NULL) result = E_UNKNOWN; else BN_CTX_init(*r_ctx); if (result != E_SUCCESS) { if (*r_ctx != NULL) BN_CTX_free(*r_ctx); *r_ctx = NULL; } return result; } SINT32 initCTX(SINT32& ar_sResult, BN_CTX** r_ctx) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initCTX(r_ctx); return ar_sResult; } void clearCTX(BN_CTX** a_ctx) { if (*a_ctx != NULL) BN_CTX_free(*a_ctx); *a_ctx = NULL; } SINT32 initBNList(BIGNUM*** r_bnList, UINT32 a_bnListSize) { if (r_bnList == NULL) return E_UNKNOWN; if (*r_bnList != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; if ((*r_bnList = new BIGNUM*[a_bnListSize]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < a_bnListSize; i++) (*r_bnList)[i] = NULL; if (result != E_SUCCESS) { delete[] *r_bnList; *r_bnList = NULL; } return result; } SINT32 initBNList(SINT32& ar_sResult, BIGNUM*** r_bnList, UINT32 a_bnListSize) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initBNList(r_bnList, a_bnListSize); return ar_sResult; } SINT32 clearBNList(UINT32 a_uListSize, BIGNUM** a_bnList, UINT8 a_uFreeArray) { if (a_bnList == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; try { for (UINT32 i = 0; i < a_uListSize; i++) if (a_bnList[i] != NULL) { BN_clear_free(a_bnList[i]); a_bnList[i] = NULL; } } catch ( ... ) { result = E_UNKNOWN; } if (a_uFreeArray != 0) delete[] a_bnList; return result; } SINT32 clearBNList(SINT32& ar_sResult, UINT32 a_uListSize, BIGNUM** a_bnList, UINT8 a_uFreeArray) { if (ar_sResult != E_SUCCESS) clearBNList(a_uListSize, a_bnList, a_uFreeArray); else ar_sResult = clearBNList(a_uListSize, a_bnList, a_uFreeArray); return ar_sResult; } SINT32 copyBNList(BIGNUM*** a_bnCopy, UINT32 a_uListSize, BIGNUM** a_bnSource) { if ((a_bnCopy == NULL) || (a_bnSource == NULL)) return E_UNKNOWN; if (*a_bnCopy != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; initBNList(result, a_bnCopy, a_uListSize); for (UINT32 i = 0; (i < a_uListSize) && (result == E_SUCCESS); i++) { if (a_bnSource[i] == NULL) continue; if (((*a_bnCopy)[i] = BN_dup(a_bnSource[i])) == NULL) result = E_UNKNOWN; } return result; } SINT32 copyBNList(SINT32& ar_sResult, BIGNUM*** a_bnCopy, UINT32 a_uListSize, BIGNUM** a_bnSource) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = copyBNList(a_bnCopy, a_uListSize, a_bnSource); return ar_sResult; } SINT32 getFreeIdx(UINT32 a_uListSize, void** a_vList) { if (a_vList == NULL) return -1; for (UINT32 i = 0; i < a_uListSize; i++) if (a_vList[i] == NULL) return i; return -1; } SINT32 insertToList(UINT32 a_uListSize, void** a_vList, void* a_vListElement) { if ((a_vList == NULL) || (a_vListElement == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; SINT32 sIdx = -1; if ((sIdx = getFreeIdx(a_uListSize, a_vList)) < 0) result = E_UNKNOWN; if (result == E_SUCCESS) a_vList[sIdx] = a_vListElement; return result; } SINT32 insertToList(CAMutex* a_pMutex, UINT32 a_uListSize, void** a_vList, void* a_vListElement) { if (a_pMutex == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; while (a_pMutex->lock() != E_SUCCESS) ; result = insertToList(a_uListSize, a_vList, a_vListElement); while (a_pMutex->unlock() != E_SUCCESS) ; return result; } SINT32 insertToMIXList(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData, MIXDATA* a_pMIXData) { return insertToList(a_pMIXMutex, a_uMIXCnt, (void**)a_vMIXData, (void*)a_pMIXData); } SINT32 deleteFromMIXList(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData, UINT32 a_uIdx) { if ((a_pMIXMutex == NULL) || (a_vMIXData == NULL) || (a_uIdx >= a_uMIXCnt)) return E_UNKNOWN; SINT32 result = E_SUCCESS; MIXDATA* pMIXData = NULL; if (a_vMIXData[a_uIdx] == NULL) result = E_UNKNOWN; else { while (a_pMIXMutex->lock() != E_SUCCESS) ; pMIXData = a_vMIXData[a_uIdx]; a_vMIXData[a_uIdx] = NULL; MIXDATA_free(pMIXData); /* ELGAMAL_free(pMIXData->elSignKey); ELGAMAL_free(pMIXData->elEncKey); delete[] pMIXData->cIP; delete pMIXData;*/ while (a_pMIXMutex->unlock() != E_SUCCESS) ; } return result; } UINT32 getMIXIdx(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData, UINT8* a_uIP, UINT32 a_uMainPort) { if ((a_vMIXData == NULL) || (a_uIP == NULL)) return 0xFFFFFFFF; UINT32 result = 0xFFFFFFFF; while (a_pMIXMutex->lock() != E_SUCCESS) ; for (UINT32 i = 0; i < a_uMIXCnt; i++) if (a_vMIXData[i] != NULL) if (a_vMIXData[i]->uMainPort == a_uMainPort) if (strcmp((char*)a_vMIXData[i]->cIP, (char*)a_uIP) == 0) { result = i; break; } while (a_pMIXMutex->unlock() != E_SUCCESS) ; return result; } SINT32 clearMIXList(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData) { if (a_pMIXMutex == NULL) return E_UNKNOWN; if (a_vMIXData == NULL) return E_SUCCESS; SINT32 result = E_SUCCESS; for (UINT32 i = 0; i < a_uMIXCnt; i++) if (deleteFromMIXList(a_pMIXMutex, a_uMIXCnt, a_vMIXData, i) != E_SUCCESS) result = E_UNKNOWN; delete[] a_vMIXData; return result; } SINT32 initMIXList(MIXDATA*** a_vMIXData, UINT32 a_uMIXCnt) { if (a_vMIXData == NULL) return E_UNKNOWN; if (*a_vMIXData != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; if ((*a_vMIXData = new MIXDATA*[a_uMIXCnt]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < a_uMIXCnt; i++) (*a_vMIXData)[i] = NULL; return result; } SINT32 initMIXList(SINT32& ar_sResult, MIXDATA*** a_vMIXData, UINT32 a_uMIXCnt) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initMIXList(a_vMIXData, a_uMIXCnt); return ar_sResult; } SINT32 getNextPermElement(SINT32& ar_sResult, UINT32& r_uNextElement, UINT32 a_uListSize, UINT32* a_uPermList, UINT32 a_uPrevElement) { if (ar_sResult != E_SUCCESS) return ar_sResult; if (a_uPermList == NULL) { ar_sResult = E_UNKNOWN; return ar_sResult; } SINT32 uIdx = getIdx(a_uListSize, a_uPermList, a_uPrevElement); if (uIdx < 0) ar_sResult = E_UNKNOWN; if (uIdx == a_uListSize - 1) uIdx = 0; else uIdx++; if (ar_sResult == E_SUCCESS) r_uNextElement = a_uPermList[uIdx]; return ar_sResult; } SINT32 getIdx(UINT32 a_uListSize, UINT32* a_uList, UINT32 a_uValue) { if (a_uList == NULL) return -1; for (UINT32 i = 0; i < a_uListSize; i++) if (a_uList[i] == a_uValue) return i; return -1; } SINT32 createRndList(UINT32** r_uList, UINT32 a_uListSize, UINT32 a_uModul) { if (r_uList == NULL) return E_UNKNOWN; if (*r_uList != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 tmp = 0; UINT8 unique = 0; if ((*r_uList = new UINT32[a_uListSize]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < a_uListSize; i++) (*r_uList)[i] = 0xFFFFFFFF; if (a_uModul >= a_uListSize) unique = 1; for (UINT32 i = 0; (i < a_uListSize) && (result == E_SUCCESS); i++) { tmp = rand() % a_uModul; while ((unique == 1) && (getIdx(a_uListSize, *r_uList, tmp) >= 0)) tmp = rand() % a_uModul; (*r_uList)[i] = tmp; } return result; } SINT32 createRndList(SINT32& ar_sResult, UINT32** r_uList, UINT32 a_uListSize, UINT32 a_uModul) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = createRndList(r_uList, a_uListSize, a_uModul); return ar_sResult; } SINT32 initSocket(CASocket** r_pSocket) { if (r_pSocket == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; // allowed on NULL delete *r_pSocket; if ((*r_pSocket = new CASocket()) == NULL) result = E_UNKNOWN; else result = (*r_pSocket)->create(); return result; } SINT32 initSocket(SINT32& ar_sResult, CASocket** r_pSocket) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initSocket(r_pSocket); return ar_sResult; } SINT32 initSocketAddrINet(CASocketAddrINet** r_pAddr) { if (r_pAddr == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; // allowed on NULL delete *r_pAddr; if ((*r_pAddr = new CASocketAddrINet()) == NULL) result = E_UNKNOWN; return result; } SINT32 initSocketAddrINet(SINT32& ar_sResult, CASocketAddrINet** r_pAddr) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initSocketAddrINet(r_pAddr); return ar_sResult; } SINT32 initAddrSocket(CASocket** r_pSocket, CASocketAddrINet** r_pAddr, UINT8* a_uIP, UINT16 a_uPort, UINT8 a_uConnect) { SINT32 result = E_SUCCESS; initSocket(result, r_pSocket); initSocketAddrINet(result, r_pAddr); if (result == E_SUCCESS) result = (*r_pAddr)->setAddr(a_uIP, a_uPort); if ((result == E_SUCCESS) && (a_uConnect != 0)) result = (*r_pSocket)->connect(**r_pAddr); return result; } SINT32 initAddrSocket(SINT32& ar_sResult, CASocket** r_pSocket, CASocketAddrINet** r_pAddr, UINT8* a_uIP, UINT16 a_uPort, UINT8 a_uConnect) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initAddrSocket(r_pSocket, r_pAddr, a_uIP, a_uPort, a_uConnect); return ar_sResult; } SINT32 initSocketList(CASocket*** r_pSockets, UINT32 a_uListSize) { if (r_pSockets == NULL) return E_UNKNOWN; if (*r_pSockets != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; if ((*r_pSockets = new CASocket*[a_uListSize]) == NULL) result = E_UNKNOWN; for (UINT32 i = 0; (i < a_uListSize) && (result == E_SUCCESS); i++) { if (((*r_pSockets)[i] = new CASocket()) == NULL) result = E_UNKNOWN; else result = (*r_pSockets)[i]->create(); } return result; } SINT32 initSocketList(SINT32& ar_sResult, CASocket*** r_pSockets, UINT32 a_uListSize) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initSocketList(r_pSockets, a_uListSize); return ar_sResult; } SINT32 clearSocketList(UINT32 a_uListSize, CASocket** a_pSockets) { if (a_pSockets == NULL) return E_UNKNOWN; for (UINT32 i = 0; i < a_uListSize; i++) { if (a_pSockets[i] != NULL) a_pSockets[i]->close(); delete a_pSockets[i]; } delete[] a_pSockets; return E_SUCCESS; } SINT32 initSocketAddrINetList(CASocketAddrINet*** r_pAddrs, UINT32 a_uListSize) { if (r_pAddrs == NULL) return E_UNKNOWN; if (*r_pAddrs != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; if ((*r_pAddrs = new CASocketAddrINet*[a_uListSize]) == NULL) result = E_UNKNOWN; for (UINT32 i = 0; (i < a_uListSize) && (result == E_SUCCESS); i++) if (((*r_pAddrs)[i] = new CASocketAddrINet()) == NULL) result = E_UNKNOWN; return result; } SINT32 initSocketAddrINetList(SINT32& ar_sResult, CASocketAddrINet*** r_pAddrs, UINT32 a_uListSize) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = initSocketAddrINetList(r_pAddrs, a_uListSize); return ar_sResult; } SINT32 clearSocketAddrINetList(UINT32 a_uListSize, CASocketAddrINet** a_pAddrs) { if (a_pAddrs == NULL) return E_SUCCESS; for (UINT32 i = 0; i < a_uListSize; i++) delete a_pAddrs[i]; delete[] a_pAddrs; return E_SUCCESS; } anon-proxy-00.05.38+20081230/FlashMix/FlashMix.cpp0000644000175000017500000000354710676452766017702 0ustar daviddavid#include "../StdAfx.h" #include "../CACmdLnOptions.hpp" #include "CAFlashMix.hpp" #ifdef __BORLANDC__ #pragma argsused #endif CACmdLnOptions* pglobalOptions; UINT8* localIP = NULL; UINT8* bbIP = NULL; UINT32 bbPort = 16000; UINT32 port = 6000; void readParam(int argc, char* argv[]) { for (int i = 0; i < argc; i++) { if (strstr(argv[i], "--port=") == argv[i]) port = atoi(argv[i] + 7); else if (strstr(argv[i], "--bbPort=") == argv[i]) bbPort = atoi(argv[i] + 9); else if (strstr(argv[i], "--bbIP=") == argv[i]) { free((char*)bbIP); bbIP = (UINT8*)strdup(argv[i] + 7); } else if (strstr(argv[i], "--localIP=") == argv[i]) { free((char*)localIP); localIP = (UINT8*)strdup(argv[i] + 10); } else if (strstr(argv[i], "/port=") == argv[i]) port = atoi(argv[i] + 6); else if (strstr(argv[i], "/bbPort=") == argv[i]) bbPort = atoi(argv[i] + 8); else if (strstr(argv[i], "/bbIP=") == argv[i]) { free((char*)bbIP); bbIP = (UINT8*)strdup(argv[i] + 8); } else if (strstr(argv[i], "/localIP=") == argv[i]) { free((char*)localIP); localIP = (UINT8*)strdup(argv[i] + 9); } } } int main( int argc, char * argv[] ) { #ifdef _WIN32 int err = 0; WSADATA wsadata; err = WSAStartup(0x0202, &wsadata); #endif CASocketAddrINet::init(); CAMsg::init(); localIP = (UINT8*)strdup("127.0.0.1"); bbIP = (UINT8*)strdup("127.0.0.1"); readParam(argc, argv); CAFlashMIX* fm = new CAFlashMIX(localIP, port, port + 1, port + 2, port + 3, port + 4, bbIP, bbPort); free((char*)localIP); free((char*)bbIP); fm->init(); fm->start(); delete fm; return 0; } anon-proxy-00.05.38+20081230/FlashMix/uBubbleSort.cpp0000644000175000017500000000006410162311576020365 0ustar daviddavid#include "../StdAfx.h" #include "uBubbleSort.hpp" anon-proxy-00.05.38+20081230/FlashMix/CABNSend.hpp0000644000175000017500000000772410162311576017471 0ustar daviddavid#ifndef __CABNSEND__ #define __CABNSEND__ #include "../CASocket.hpp" #include "elgamal.hpp" SINT32 sendUINT32(CASocket* a_pClient, UINT32 a_uValue); SINT32 receiveUINT32(UINT32& r_uValue, CASocket* a_pClient); SINT32 sendUINT32(SINT32& ar_sResult, CASocket* a_pClient, UINT32 a_uValue); SINT32 receiveUINT32(SINT32& ar_sResult, UINT32& r_uValue, CASocket* a_pClient); SINT32 sendPChar(CASocket* a_pClient, UINT8* a_uChar); SINT32 receivePChar(UINT8** r_uChar, CASocket* a_pClient); SINT32 sendPChar(SINT32& ar_sResult, CASocket* a_pClient, UINT8* a_uChar); SINT32 receivePChar(SINT32& ar_sResult, UINT8** r_uChar, CASocket* a_pClient); SINT32 sendUINT8Arr(CASocket* a_pClient, UINT32 a_uSize, UINT8* a_uArr); SINT32 receiveUINT8Arr(UINT32& r_uSize, UINT8** r_uArr, CASocket* a_pClient); SINT32 sendUINT8Arr(SINT32& ar_sResult, CASocket* a_pClient, UINT32 a_uSize, UINT8* a_uArr); SINT32 receiveUINT8Arr(SINT32& ar_sResult, UINT32& r_uSize, UINT8** r_uArr, CASocket* a_pClient); SINT32 sendBN(CASocket* a_pClient, BIGNUM* a_bn); SINT32 receiveBN(BIGNUM** r_bn, CASocket* a_pClient); SINT32 sendBN(SINT32& ar_sResult, CASocket* a_pClient, BIGNUM* a_bn); SINT32 receiveBN(SINT32& ar_sResult, BIGNUM** r_bn, CASocket* a_pClient); SINT32 sendSignedBN(ELGAMAL* a_elSignKey, CASocket* a_pClient, BIGNUM* a_bn); SINT32 receiveSignedBN(BIGNUM** r_bn, ELGAMAL* a_elTestKey, CASocket* a_pClient); SINT32 sendSignedBN(SINT32& ar_sResult, ELGAMAL* a_elSignKey, CASocket* a_pClient, BIGNUM* a_bn); SINT32 receiveSignedBN(SINT32& ar_sResult, BIGNUM** r_bn, ELGAMAL* a_elTestKey, CASocket* a_pClient); SINT32 sendEncSignedBN(ELGAMAL* a_elSignKey, ELGAMAL* a_elEncKey, CASocket* a_pClient, BIGNUM* a_bn); SINT32 receiveEncSignedBN(BIGNUM** r_bn, ELGAMAL* a_elTestKey, ELGAMAL* a_elDecryptKey, CASocket* a_pClient); SINT32 sendEncSignedBN(SINT32& ar_sResult, ELGAMAL* a_elSignKey, ELGAMAL* a_elEncKey, CASocket* a_pClient, BIGNUM* a_bn); SINT32 receiveEncSignedBN(SINT32& ar_sResult, BIGNUM** r_bn, ELGAMAL* a_elTestKey, ELGAMAL* a_elDecryptKey, CASocket* a_pClient); SINT32 sendPublicKey(CASocket* a_pClient, ELGAMAL* a_elKey); SINT32 receivePublicKey(ELGAMAL** r_elKey, CASocket* a_pClient); SINT32 sendPublicKey(SINT32& ar_sResult, CASocket* a_pClient, ELGAMAL* a_elKey); SINT32 receivePublicKey(SINT32& ar_sResult, ELGAMAL** r_elKey, CASocket* a_pClient); SINT32 sendSignedPublicKey(ELGAMAL* a_elSignKey, CASocket* a_pClient, ELGAMAL* a_elKey); SINT32 receiveSignedPublicKey(ELGAMAL** r_elKey, ELGAMAL* a_elTestKey, CASocket* a_pClient); SINT32 sendSignedPublicKey(SINT32& ar_sResult, ELGAMAL* a_elSignKey, CASocket* a_pClient, ELGAMAL* a_elKey); SINT32 receiveSignedPublicKey(SINT32& ar_sResult, ELGAMAL** r_elKey, ELGAMAL* a_elTestKey, CASocket* a_pClient); SINT32 sendSignedBNArray(ELGAMAL* a_elSignKey, CASocket* a_pClient, UINT32 a_uBNArrLength, BIGNUM** a_bnArr); SINT32 receiveSignedBNArray(UINT32& r_uBNArrLength, BIGNUM*** r_bnArr, ELGAMAL* a_elTestKey, CASocket* a_pClient); SINT32 sendSignedBNArray(SINT32& ar_sResult, ELGAMAL* a_elSignKey, CASocket* a_pClient, UINT32 a_uBNArrLength, BIGNUM** a_bnArr); SINT32 receiveSignedBNArray(SINT32& ar_sResult, UINT32& r_uBNArrLength, BIGNUM*** r_bnArr, ELGAMAL* a_elTestKey, CASocket* a_pClient); SINT32 BN_bnArr2pCharArr(UINT8*** r_uPCharArray, UINT32 a_bnArrSize, BIGNUM** a_bnArr); SINT32 BN_bnArr2pCharArr(SINT32& ar_sResult, UINT8*** r_uPCharArray, UINT32 a_bnArrSize, BIGNUM** a_bnArr); SINT32 BN_pCharArr2bnArr(BIGNUM*** r_bnArr, UINT32 a_bnArrSize, UINT8** a_uPChar); SINT32 BN_pCharArr2bnArr(SINT32& ar_sResult, BIGNUM*** r_bnArr, UINT32 a_bnArrSize, UINT8** a_uPChar); SINT32 pCharArr2pChar(UINT8** r_uPChar, UINT32 a_uArrSize, UINT8** a_uPCharArr); SINT32 pCharArr2pChar(SINT32& ar_sResult, UINT8** r_uPChar, UINT32 a_uArrSize, UINT8** a_uPCharArr); SINT32 BN_bnArr2UINT8Arr(UINT32& r_uSize, UINT8** r_uArr, UINT32 a_uBNArrSize, BIGNUM** a_bnArr); SINT32 BN_bnArr2UINT8Arr(SINT32& ar_sResult, UINT32& r_uSize, UINT8** r_uArr, UINT32 a_uBNArrSize, BIGNUM** a_bnArr); #endif // __CABNSEND__ anon-proxy-00.05.38+20081230/FlashMix/CABulletinBoard.cpp0000644000175000017500000006503710170075440021076 0ustar daviddavid#include "../StdAfx.h" #include "CABulletinBoard.hpp" #include #include void log(int line, SINT32 result, char* des) { std::cout << "Line: " << line << " Result: " << result << " " << des << std::endl; } void coutbn(BIGNUM* bn) { char* c = BN_bn2dec(bn); std::cout << c << std::endl; OPENSSL_free(c); } void coutElGamal(char* a_suffix, ELGAMAL* el) { std::cout << a_suffix << "->p = "; coutbn(el->p); std::cout << a_suffix << "->pm1 = "; coutbn(el->pm1); std::cout << a_suffix << "->q = "; coutbn(el->q); std::cout << a_suffix << "->g = "; coutbn(el->g); std::cout << a_suffix << "->x = "; coutbn(el->x); std::cout << a_suffix << "->y = "; coutbn(el->y); } CABulletinBoard::CABulletinBoard( UINT32 a_uPort, UINT32 a_uKeyLength, UINT32 a_uMIXCnt, UINT32 a_uMIXPermCnt, UINT32 a_uMIXDecryptCnt, UINT32 a_uAnonCnt) : CAMainThread(a_uPort, handleRequest) { m_uKeyLength = a_uKeyLength; m_uMIXCnt = a_uMIXCnt; m_uMIXPermCnt = a_uMIXPermCnt; m_uMIXDecryptCnt = a_uMIXDecryptCnt; m_uAnonCnt = a_uAnonCnt; m_uAnonListSize = 2 * m_uAnonCnt + 4; m_elSignKey = NULL; m_elEncKey = NULL; m_elGroupKey = NULL; // MIX data initialize m_vMIXData = NULL; initMIXList(&m_vMIXData, m_uMIXCnt); m_uUserMsgListPtr = 0; m_pMutexMIXData = new CAMutex(); // init user msg m_vBNUserMsg = NULL; initBNList(&m_vBNUserMsg, m_uAnonListSize); m_pMutexUserMsg = new CAMutex(); CAMsg::init(); } CABulletinBoard::~CABulletinBoard() { stop(); join(); ELGAMAL_free(m_elSignKey); ELGAMAL_free(m_elEncKey); ELGAMAL_free(m_elGroupKey); clearMIXList(m_pMutexMIXData, m_uMIXCnt, m_vMIXData); delete m_pMutexMIXData; clearBNList(m_uAnonListSize, m_vBNUserMsg, 1); delete m_pMutexUserMsg; } SINT32 CABulletinBoard::init() { SINT32 result = E_SUCCESS; CAMsg::printMsg(LOG_DEBUG, "key generation: encryption key startet\n"); if ((m_elSignKey = ELGAMAL_generate_key(m_uKeyLength)) == NULL) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "key generation: encryption key %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); CAMsg::printMsg(LOG_DEBUG, "key generation: signature key startet\n"); if ((m_elEncKey = ELGAMAL_generate_key(m_uKeyLength)) == NULL) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "key generation: signature key %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); return result; } SINT32 CABulletinBoard::insertToUserList(BIGNUM* a_bnA, BIGNUM* a_bnB) { if ((a_bnA == NULL) || (a_bnB == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; if (m_uUserMsgListPtr >= m_uAnonListSize - 4) result = E_UNKNOWN; else { if ((m_vBNUserMsg[m_uUserMsgListPtr] != NULL) || (m_vBNUserMsg[m_uUserMsgListPtr + 1] != NULL)) result = E_UNKNOWN; else { m_vBNUserMsg[m_uUserMsgListPtr] = a_bnA; m_vBNUserMsg[m_uUserMsgListPtr + 1] = a_bnB; m_uUserMsgListPtr += 2; } } return result; } SINT32 CABulletinBoard::insertToUserList(SINT32& ar_sResult, BIGNUM* a_bnA, BIGNUM* a_bnB) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = insertToUserList(a_bnA, a_bnB); return ar_sResult; } SINT32 CABulletinBoard::insertDummy(BIGNUM** ar_bnList, BIGNUM* a_bnDummyA, BIGNUM* a_bnDummyB) { if ((ar_bnList == NULL) || (a_bnDummyA == NULL) || (a_bnDummyB == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; SINT32 sIdx = -1; if ((sIdx = getFreeIdx(m_uAnonListSize, (void**)ar_bnList)) < 0) result = E_UNKNOWN; else { ar_bnList[sIdx] = a_bnDummyA; ar_bnList[sIdx + 1] = a_bnDummyB; } return result; } SINT32 CABulletinBoard::insertDummy(SINT32& ar_sResult, BIGNUM** ar_bnList, BIGNUM* a_bnDummyA, BIGNUM* a_bnDummyB) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = insertDummy(ar_bnList, a_bnDummyA, a_bnDummyB); return ar_sResult; } SINT32 CABulletinBoard::sendSignKey(CABulletinBoard* a_ths, CASocket* a_pClient) { return sendPublicKey(a_pClient, a_ths->m_elSignKey); } SINT32 CABulletinBoard::sendEncKey(CABulletinBoard* a_ths, CASocket* a_pClient) { return sendSignedPublicKey(a_ths->m_elSignKey, a_pClient, a_ths->m_elEncKey); } SINT32 CABulletinBoard::sendGroupKey(CABulletinBoard* a_ths, CASocket* a_pClient) { return sendSignedPublicKey(a_ths->m_elSignKey, a_pClient, a_ths->m_elGroupKey); } THREAD_RETURN CABulletinBoard::handleRequest(void* a_req) { CABulletinBoard* ths = (CABulletinBoard*)((UINT32*)a_req)[0]; CASocket* pClient = (CASocket*)((UINT32*)a_req)[1]; UINT32 reqCode = BB_REQ_UNDEF; delete[] (UINT32*)a_req; if (receiveUINT32(reqCode, pClient) == E_SUCCESS) { switch (reqCode) { case BB_REQ_USER_DATA: receiveUserData(ths, pClient); break; case BB_REQ_INIT_MIX: initMix(ths, pClient); break; case BB_REQ_REMOVE_MIX: removeMix(ths, pClient); break; case BB_REQ_GET_SIGN_KEY: sendSignKey(ths, pClient); break; case BB_REQ_GET_ENC_KEY: sendEncKey(ths, pClient); break; case BB_REQ_GET_GROUP_KEY: sendGroupKey(ths, pClient); break; } } if (pClient != NULL) pClient->close(); delete pClient; THREAD_RETURN_SUCCESS; } THREAD_RETURN CABulletinBoard::keyShareing(void* a_thisPtr) { SINT32 result = E_SUCCESS; CABulletinBoard* ths = (CABulletinBoard*)a_thisPtr; CASocket** pSockets = NULL; CASocketAddrINet** pAddrs = NULL; BIGNUM* bnY = NULL; BN_CTX* ctx = NULL; UINT32 procRes = PROCESS_UNDEF; CAMsg::printMsg(LOG_DEBUG, "key shareing startet\n"); // init all variables ELGAMAL_free(ths->m_elGroupKey); if ((ths->m_elGroupKey = ELGAMAL_generate_key(ths->m_uKeyLength)) == NULL) result = E_UNKNOWN; initSocketList(result, &pSockets, ths->m_uMIXCnt); initSocketAddrINetList(result, &pAddrs, ths->m_uMIXCnt); initBN(result, &bnY, 1); initCTX(result, &ctx); // connect to all mixes and send mix data for (UINT32 i = 0; (i < ths->m_uMIXCnt) && (result == E_SUCCESS) && (ths->m_vMIXData != NULL); i++) { if (ths->m_vMIXData[i] == NULL) { result = E_UNKNOWN; continue; } if (result == E_SUCCESS) result = pAddrs[i]->setAddr(ths->m_vMIXData[i]->cIP, ths->m_vMIXData[i]->uMainPort); if (result == E_SUCCESS) { pSockets[i]->create(); result = pSockets[i]->connect(*(pAddrs[i]), 5000, 1); } sendUINT32(result, pSockets[i], MIX_REQ_KEY_SHARE); // send MIX Data for (UINT32 j = 0; (j < ths->m_uMIXCnt) && (result == E_SUCCESS); j++) { sendPChar(result, pSockets[i], ths->m_vMIXData[j]->cIP); sendUINT32(result, pSockets[i], ths->m_vMIXData[j]->uMainPort); sendUINT32(result, pSockets[i], ths->m_vMIXData[j]->uPortKeyShare); sendUINT32(result, pSockets[i], ths->m_vMIXData[j]->uPortDummy); sendUINT32(result, pSockets[i], ths->m_vMIXData[j]->uPortBlind); sendUINT32(result, pSockets[i], ths->m_vMIXData[j]->uPortDecrypt); sendSignedPublicKey(result, ths->m_elSignKey, pSockets[i], ths->m_vMIXData[j]->elSignKey); sendSignedPublicKey(result, ths->m_elSignKey, pSockets[i], ths->m_vMIXData[j]->elEncKey); } sendSignedPublicKey(result, ths->m_elSignKey, pSockets[i], ths->m_elGroupKey); } CAMsg::printMsg(LOG_DEBUG, "connect to mixes and data send: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // wait for g^xi and calc y for (UINT32 i = 0; (i < ths->m_uMIXCnt) && (result == E_SUCCESS); i++) { BIGNUM* bnTmp = NULL; receiveSignedBN(result, &bnTmp, ths->m_vMIXData[i]->elSignKey, pSockets[i]); if (result == E_SUCCESS) if (BN_mod_mul(bnY, bnY, bnTmp, ths->m_elGroupKey->p, ctx) == 0) result = E_UNKNOWN; if (bnTmp != NULL) BN_free(bnTmp); } CAMsg::printMsg(LOG_DEBUG, "y calc: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // calc public y if (result == E_SUCCESS) { if (ths->m_elGroupKey->y != NULL) BN_free(ths->m_elGroupKey->y); ths->m_elGroupKey->y = bnY; } else if (bnY != NULL) BN_free(bnY); // send the group y for (UINT32 i = 0; (i < ths->m_uMIXCnt) && (result == E_SUCCESS); i++) sendSignedBN(result, ths->m_elSignKey, pSockets[i], bnY); // wait for MIX okay procRes = PROCESS_SUCCESS; for (UINT32 i = 0; (i < ths->m_uMIXCnt) && (result == E_SUCCESS) && (procRes == PROCESS_SUCCESS); i++) receiveUINT32(result, procRes, pSockets[i]); if (procRes != PROCESS_SUCCESS) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "key shareing: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // bnY is freed in m_elGroupKey if (ctx != NULL) BN_CTX_free(ctx); clearSocketList(ths->m_uMIXCnt, pSockets); clearSocketAddrINetList(ths->m_uMIXCnt, pAddrs); THREAD_RETURN_SUCCESS; } THREAD_RETURN CABulletinBoard::mixProcess(void* a_thisPtr) { CABulletinBoard* ths = (CABulletinBoard*)a_thisPtr; SINT32 result = E_SUCCESS; UINT32 procRes = UNBLIND_UNDEF; UINT32* uPermList = NULL; UINT32* uDecList = NULL; CASocket** pSockets = NULL; CASocketAddrINet** pAddrs = NULL; BIGNUM** vBNUserMsg = NULL; BIGNUM** bnDummies = NULL; BIGNUM** bnFirstListFirstReenc = NULL; BIGNUM** bnSecondListFirstReenc = NULL; BIGNUM** bnFirstListSecondReenc = NULL; BIGNUM** bnSecondListSecondReenc = NULL; BIGNUM** bnCopyFirstList = NULL; UINT32 uDummyPos1 = 0xFFFFFFFF; UINT32 uDummyPos2 = 0xFFFFFFFF; // create copy of userlist (pointer copy only) // copy the list (pointer only) vBNUserMsg = ths->m_vBNUserMsg; // clear user list ths->m_vBNUserMsg = NULL; initBNList(result, &(ths->m_vBNUserMsg), ths->m_uAnonListSize); ths->m_uUserMsgListPtr = 0; ths->m_pMutexUserMsg->unlock(); CAMsg::printMsg(LOG_DEBUG, "mix process startet\n"); // init all variables initSocketList(result, &pSockets, ths->m_uMIXPermCnt); initSocketAddrINetList(result, &pAddrs, ths->m_uMIXPermCnt); createRndList(result, &uPermList, ths->m_uMIXPermCnt, ths->m_uMIXCnt); createRndList(result, &uDecList, ths->m_uMIXDecryptCnt, ths->m_uMIXCnt); // BubbleSort(uDecList, ths->m_uMIXDecryptCnt); // for (UINT32 i = 0; i < ths->m_uMIXDecryptCnt; i++) // uDecList[i] = i; /* for (UINT32 i = 0; (i < ths->m_uMIXPermCnt) && (result == E_SUCCESS); i++) CAMsg::printMsg(LOG_DEBUG, "Permutation[%d] = %d\n", i, uPermList[i]);/**/ /* for (UINT32 i = 0; (i < ths->m_uMIXDecryptCnt) && (result == E_SUCCESS); i++) CAMsg::printMsg(LOG_DEBUG, "Permutation[%d] = %d\n", i, uDecList[i]);/**/ // connect to permutation mixes and send permutation list for (UINT32 i = 0; (i < ths->m_uMIXPermCnt) && (result == E_SUCCESS); i++) { MIXDATA* pMIXData = ths->m_vMIXData[uPermList[i]]; result = pAddrs[i]->setAddr(pMIXData->cIP, pMIXData->uMainPort); if (result == E_SUCCESS) result = pSockets[i]->connect((*pAddrs[i]), 5000, 1); sendUINT32(result, pSockets[i], MIX_REQ_MIX_PROCESS); // send request sendUINT32(result, pSockets[i], i); // send list index // send list for (UINT32 j = 0; (j < ths->m_uMIXPermCnt) && (result == E_SUCCESS); j++) sendUINT32(result, pSockets[i], uPermList[j]); } CAMsg::printMsg(LOG_DEBUG, "permutation data send: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // create Dummy if (result == E_SUCCESS) result = createDummies(&bnDummies, ths, pSockets, uPermList); CAMsg::printMsg(LOG_DEBUG, "dummy creation: %s\n", (result == E_SUCCESS) ? "received successfull" : "ERROR on receive"); // append dummies if (result == E_SUCCESS) { if (ths->insertDummy(result, vBNUserMsg, bnDummies[0], bnDummies[1]) != E_SUCCESS) { if (bnDummies[0] != NULL) BN_free(bnDummies[0]); if (bnDummies[1] != NULL) BN_free(bnDummies[1]); } if (ths->insertDummy(result, vBNUserMsg, bnDummies[2], bnDummies[3]) != E_SUCCESS) { if (bnDummies[2] != NULL) BN_free(bnDummies[2]); if (bnDummies[3] != NULL) BN_free(bnDummies[3]); } } CAMsg::printMsg(LOG_DEBUG, "dummies: %s to messagelist\n", (result == E_SUCCESS) ? "successfully added" : "ERROR on add"); // work on input list if (result == E_SUCCESS) result = blind(&bnFirstListFirstReenc, &bnSecondListFirstReenc, &bnFirstListSecondReenc, &bnSecondListSecondReenc, ths, pSockets, uPermList, vBNUserMsg); // send blind ok for (UINT32 i = 0; i < ths->m_uMIXPermCnt; i++) { if (result == E_SUCCESS) sendUINT32(result, pSockets[i], BLIND_SUCCESS); else sendUINT32(pSockets[i], BLIND_ERROR); } CAMsg::printMsg(LOG_DEBUG, "blinding: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // send the Lists to the mixes for unblinding for (UINT32 i = 0; (i < ths->m_uMIXPermCnt) && (result == E_SUCCESS); i++) { sendSignedBNArray(result, ths->m_elSignKey, pSockets[i], ths->m_uAnonListSize, vBNUserMsg); sendSignedBNArray(result, ths->m_elSignKey, pSockets[i], ths->m_uAnonListSize, bnFirstListFirstReenc); sendSignedBNArray(result, ths->m_elSignKey, pSockets[i], ths->m_uAnonListSize, bnSecondListFirstReenc); sendSignedBNArray(result, ths->m_elSignKey, pSockets[i], ths->m_uAnonListSize, bnFirstListSecondReenc); sendSignedBNArray(result, ths->m_elSignKey, pSockets[i], ths->m_uAnonListSize, bnSecondListSecondReenc); } CAMsg::printMsg(LOG_DEBUG, "lists send to mixes: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // wait for the dummy-positions from last mix receiveUINT32(result, uDummyPos1, pSockets[ths->m_uMIXPermCnt - 1]); receiveUINT32(result, uDummyPos2, pSockets[ths->m_uMIXPermCnt - 1]); // CAMsg::printMsg(LOG_DEBUG, "Pos 1: %d\n", uDummyPos1); // CAMsg::printMsg(LOG_DEBUG, "Pos 2: %d\n", uDummyPos2); if (uDummyPos2 < uDummyPos1) { UINT32 uTmp = uDummyPos1; uDummyPos1 = uDummyPos2; uDummyPos2 = uTmp; } // remove dummies from list if (result == E_SUCCESS) if ((bnCopyFirstList = new BIGNUM*[ths->m_uAnonListSize - 4]) == NULL) result = E_UNKNOWN; for (UINT32 i = 0; (i < 2*uDummyPos1) && (result == E_SUCCESS); i += 2) { bnCopyFirstList[i] = bnFirstListSecondReenc[i]; bnCopyFirstList[i+1] = bnFirstListSecondReenc[i+1]; } for (UINT32 i = 2*(uDummyPos1 + 1); (i < 2*uDummyPos2) && (result == E_SUCCESS); i += 2) { bnCopyFirstList[i - 2] = bnFirstListSecondReenc[i]; bnCopyFirstList[i - 1] = bnFirstListSecondReenc[i + 1]; } for (UINT32 i = 2*(uDummyPos2 + 1); (i < ths->m_uAnonListSize) && (result == E_SUCCESS); i += 2) { bnCopyFirstList[i - 4] = bnFirstListSecondReenc[i]; bnCopyFirstList[i - 3] = bnFirstListSecondReenc[i + 1]; } // wait for unblind result procRes = UNBLIND_SUCCESS; for (UINT32 i = 0; (i < ths->m_uMIXPermCnt) && (result == E_SUCCESS) && (procRes == UNBLIND_SUCCESS); i++) receiveUINT32(result, procRes, pSockets[i]); if (procRes != UNBLIND_SUCCESS) result = E_UNKNOWN;/**/ CAMsg::printMsg(LOG_DEBUG, "unblinding: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); CAMsg::printMsg(LOG_DEBUG, "mix process finished\n"); // decrypt clearSocketList(ths->m_uMIXPermCnt, pSockets); clearSocketAddrINetList(ths->m_uMIXPermCnt, pAddrs); pSockets = NULL; pAddrs = NULL; CAMsg::printMsg(LOG_DEBUG, "decryption started\n"); initSocketList(result, &pSockets, ths->m_uMIXDecryptCnt); initSocketAddrINetList(result, &pAddrs, ths->m_uMIXDecryptCnt); // connect to decryption mixes and send decryption list for (UINT32 i = 0; (i < ths->m_uMIXDecryptCnt) && (result == E_SUCCESS); i++) { MIXDATA* pMIXData = ths->m_vMIXData[uDecList[i]]; result = pAddrs[i]->setAddr(pMIXData->cIP, pMIXData->uMainPort); if (result == E_SUCCESS) result = pSockets[i]->connect((*pAddrs[i]), 5000, 1); sendUINT32(result, pSockets[i], MIX_REQ_DECRYPT); // send request sendUINT32(result, pSockets[i], i); // send list index // send list for (UINT32 j = 0; (j < ths->m_uMIXDecryptCnt) && (result == E_SUCCESS); j++) sendUINT32(result, pSockets[i], uDecList[j]); } CAMsg::printMsg(LOG_DEBUG, "decryption list send to mixes: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // send the list for decryption to the first mix if (result == E_SUCCESS) result = sendSignedBNArray(ths->m_elSignKey, pSockets[0], ths->m_uAnonListSize - 4, bnCopyFirstList); CAMsg::printMsg(LOG_DEBUG, "inputlist send: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // wait for result procRes = DECRYPT_SUCCESS; for (UINT32 i = 0; (i < ths->m_uMIXDecryptCnt) && (result == E_SUCCESS) && (procRes == DECRYPT_SUCCESS); i++) receiveUINT32(result, procRes, pSockets[i]); if (procRes != DECRYPT_SUCCESS) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "decryption: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // free all variables delete[] bnCopyFirstList; delete[] bnDummies; // the bignum's are freed in vBNUserMsg clearBNList(ths->m_uAnonListSize, vBNUserMsg, 1); clearBNList(ths->m_uAnonListSize, bnFirstListFirstReenc, 1); clearBNList(ths->m_uAnonListSize, bnSecondListFirstReenc, 1); clearBNList(ths->m_uAnonListSize, bnFirstListSecondReenc, 1); clearBNList(ths->m_uAnonListSize, bnSecondListSecondReenc, 1); clearSocketList(ths->m_uMIXDecryptCnt, pSockets); clearSocketAddrINetList(ths->m_uMIXDecryptCnt, pAddrs); delete[] uDecList; delete[] uPermList; THREAD_RETURN_SUCCESS; } SINT32 CABulletinBoard::initMix(CABulletinBoard* a_ths, CASocket* a_pClient) { if ((a_ths == NULL) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; MIXDATA* pMIXData = NULL; // send local data sendUINT32(result, a_pClient, a_ths->m_uKeyLength); sendUINT32(result, a_pClient, a_ths->m_uMIXCnt); sendUINT32(result, a_pClient, a_ths->m_uMIXPermCnt); sendUINT32(result, a_pClient, a_ths->m_uMIXDecryptCnt); sendPublicKey(result, a_pClient, a_ths->m_elSignKey); sendSignedPublicKey(result, a_ths->m_elSignKey, a_pClient, a_ths->m_elEncKey); CAMsg::printMsg(LOG_DEBUG, "BulletinBoard data send: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); if ((pMIXData = MIXDATA_new()) == NULL) result = E_UNKNOWN; receivePChar(result, &(pMIXData->cIP), a_pClient); receiveUINT32(result, pMIXData->uMainPort, a_pClient); receiveUINT32(result, pMIXData->uPortKeyShare, a_pClient); receiveUINT32(result, pMIXData->uPortDummy, a_pClient); receiveUINT32(result, pMIXData->uPortBlind, a_pClient); receiveUINT32(result, pMIXData->uPortDecrypt, a_pClient); receivePublicKey(result, &(pMIXData->elSignKey), a_pClient); receiveSignedPublicKey(result, &(pMIXData->elEncKey), pMIXData->elSignKey, a_pClient); CAMsg::printMsg(LOG_DEBUG, "mix data receive: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); if (result == E_SUCCESS) result = insertToMIXList(a_ths->m_pMutexMIXData, a_ths->m_uMIXCnt, a_ths->m_vMIXData, pMIXData); if ((result != E_SUCCESS) && (pMIXData != NULL)) MIXDATA_free(pMIXData); if (result == E_SUCCESS) result = sendUINT32(a_pClient, PROCESS_SUCCESS); else sendUINT32(a_pClient, PROCESS_ERROR); if (result == E_SUCCESS) CAMsg::printMsg(LOG_DEBUG, "MIX %s:%d successfully added\n", (char*)pMIXData->cIP, pMIXData->uMainPort); else CAMsg::printMsg(LOG_DEBUG, "MIX %s:%d adding ERROR\n", (char*)pMIXData->cIP, pMIXData->uMainPort); // start key shareing if (result == E_SUCCESS) startKeyShareing(a_ths); return result; } SINT32 CABulletinBoard::removeMix(CABulletinBoard* a_ths, CASocket* a_pClient) { if ((a_ths == NULL) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT8* uC = NULL; UINT32 uMainPort = 0; UINT32 uMIXIdx = 0xFFFFFFFF; receivePChar(result, &uC, a_pClient); receiveUINT32(result, uMainPort, a_pClient); if (result == E_SUCCESS) if ((uMIXIdx = getMIXIdx(a_ths->m_pMutexMIXData, a_ths->m_uMIXCnt, a_ths->m_vMIXData, uC, uMainPort)) >= a_ths->m_uMIXCnt) result = E_UNKNOWN; if (result == E_SUCCESS) result = deleteFromMIXList(a_ths->m_pMutexMIXData, a_ths->m_uMIXCnt, a_ths->m_vMIXData, uMIXIdx); if (result == E_SUCCESS) result = sendUINT32(a_pClient, PROCESS_SUCCESS); else sendUINT32(a_pClient, PROCESS_ERROR); if (result == E_SUCCESS) CAMsg::printMsg(LOG_DEBUG, "MIX %s:%d successfully removed\n", (char*)uC, uMainPort); else CAMsg::printMsg(LOG_DEBUG, "MIX %s:%d ERROR on remove\n", (char*)uC, uMainPort); delete[] uC; return result; } SINT32 CABulletinBoard::startKeyShareing(CABulletinBoard* a_ths) { SINT32 result = E_SUCCESS; UINT8 start = 1; for (UINT32 i = 0; (i < a_ths->m_uMIXCnt) && (start == 1); i++) if (a_ths->m_vMIXData[i] == NULL) start = 0; if (start == 1) { pthread_t pThread; pthread_create(&pThread, NULL, keyShareing, a_ths); } return result; } SINT32 CABulletinBoard::receiveUserData(CABulletinBoard* a_ths, CASocket* a_pClient) { if ((a_ths == NULL) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM* bnEncA = NULL; BIGNUM* bnEncB = NULL; UINT8 uThread = 0; receiveBN(result, &bnEncA, a_pClient); receiveBN(result, &bnEncB, a_pClient); a_ths->m_pMutexUserMsg->lock(); if (a_ths->insertToUserList(result, bnEncA, bnEncB) != E_SUCCESS) { if (bnEncA != NULL) BN_free(bnEncA); if (bnEncB != NULL) BN_free(bnEncB); } if (result == E_SUCCESS) { if (a_ths->m_uUserMsgListPtr >= a_ths->m_uAnonListSize - 4) // if (getFreeIdx(a_ths->m_uAnonListSize - 4, (void**)a_ths->m_vBNUserMsg) == -1) { // userlist full, start mix process pthread_t pThread; pthread_create(&pThread, NULL, mixProcess, a_ths); uThread = 1; } } if (uThread != 1) a_ths->m_pMutexUserMsg->unlock(); if (result != E_SUCCESS) CAMsg::printMsg(LOG_DEBUG, "ERROR on adding user message\n"); if (result == E_SUCCESS) result = sendUINT32(a_pClient, USERDATA_SUCCESS); else sendUINT32(a_pClient, USERDATA_ERROR); return result; } SINT32 CABulletinBoard::createDummies(BIGNUM*** r_bnDummyList, CABulletinBoard* a_ths, CASocket** a_pSockets, UINT32* a_uPermList, UINT32 DUMMYCNT) { if ((r_bnDummyList == NULL) || (a_ths == NULL) || (a_pSockets == NULL) || (a_uPermList == NULL)) return E_UNKNOWN; if (*r_bnDummyList != NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uTmp = 0; MIXDATA* pMIXData = NULL; // init dummy list initBNList(result, r_bnDummyList, DUMMYCNT * 2); for (UINT32 i = 0; (i < DUMMYCNT * 2) && (result == E_SUCCESS); i++) initBNRand(result, &((*r_bnDummyList)[i]), a_ths->m_uKeyLength); // send dummies sendSignedBNArray(result, a_ths->m_elSignKey, a_pSockets[0], DUMMYCNT * 2, *r_bnDummyList); // free dummy list clearBNList(DUMMYCNT * 2, *r_bnDummyList, 1); *r_bnDummyList = NULL; // receive Dummy list pMIXData = a_ths->m_vMIXData[a_uPermList[a_ths->m_uMIXPermCnt - 1]]; // last permutation mix receiveSignedBNArray(result, uTmp, r_bnDummyList, pMIXData->elSignKey, a_pSockets[a_ths->m_uMIXPermCnt - 1]); return result; } SINT32 CABulletinBoard::blind(BIGNUM*** r_bnFirstListFirstReenc, BIGNUM*** r_bnSecondListFirstReenc, BIGNUM*** r_bnFirstListSecondReenc, BIGNUM*** r_bnSecondListSecondReenc, CABulletinBoard* a_ths, CASocket** a_pSockets, UINT32* a_uPermList, BIGNUM** a_bnInputList) { if ((r_bnFirstListFirstReenc == NULL) || (r_bnSecondListFirstReenc == NULL) || (r_bnFirstListSecondReenc == NULL) || (r_bnSecondListSecondReenc == NULL) || (a_ths == NULL) || (a_uPermList == NULL) || (a_uPermList == NULL) || (a_bnInputList == NULL)) return E_UNKNOWN; if ((*r_bnFirstListFirstReenc != NULL) || (*r_bnSecondListFirstReenc != NULL) || (*r_bnFirstListSecondReenc != NULL) || (*r_bnSecondListSecondReenc != NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uTmp = 0; MIXDATA* pMIXData = NULL; // send the first input list sendSignedBNArray(result, a_ths->m_elSignKey, a_pSockets[0], a_ths->m_uAnonListSize, a_bnInputList); // send the second input list sendSignedBNArray(result, a_ths->m_elSignKey, a_pSockets[0], a_ths->m_uAnonListSize, a_bnInputList); pMIXData = a_ths->m_vMIXData[a_uPermList[a_ths->m_uMIXPermCnt - 1]]; // last permutation mix // receive the first input list receiveSignedBNArray(result, uTmp, r_bnFirstListFirstReenc, pMIXData->elSignKey, a_pSockets[a_ths->m_uMIXPermCnt - 1]); // receibe the second input list receiveSignedBNArray(result, uTmp, r_bnSecondListFirstReenc, pMIXData->elSignKey, a_pSockets[a_ths->m_uMIXPermCnt - 1]); // send first list for second reencryption sendSignedBNArray(result, a_ths->m_elSignKey, a_pSockets[0], a_ths->m_uAnonListSize, *r_bnFirstListFirstReenc); // send second list for second reencryption sendSignedBNArray(result, a_ths->m_elSignKey, a_pSockets[0], a_ths->m_uAnonListSize, *r_bnSecondListFirstReenc); // receive the first input list receiveSignedBNArray(result, uTmp, r_bnFirstListSecondReenc, pMIXData->elSignKey, a_pSockets[a_ths->m_uMIXPermCnt - 1]); // receibe the second input list receiveSignedBNArray(result, uTmp, r_bnSecondListSecondReenc, pMIXData->elSignKey, a_pSockets[a_ths->m_uMIXPermCnt - 1]); return result; } anon-proxy-00.05.38+20081230/FlashMix/BulletinBoard.vcproj0000644000175000017500000002475610763776144021437 0ustar daviddavid anon-proxy-00.05.38+20081230/FlashMix/CABNSend.cpp0000644000175000017500000006215610162311576017464 0ustar daviddavid#include "../StdAfx.h" #include "CABNSend.hpp" // send and receive UINT32 SINT32 sendUINT32(CASocket* a_pClient, UINT32 a_uValue) { if (a_pClient == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; result = a_pClient->sendFully((UINT8*)&a_uValue, sizeof(UINT32)); return result; } SINT32 receiveUINT32(UINT32& r_uValue, CASocket* a_pClient) { if (a_pClient == NULL) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uValue = 0; result = a_pClient->receiveFully((UINT8*)&uValue, sizeof(UINT32)); r_uValue = uValue; return result; } SINT32 sendUINT32(SINT32& ar_sResult, CASocket* a_pClient, UINT32 a_uValue) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendUINT32(a_pClient, a_uValue); return ar_sResult; } SINT32 receiveUINT32(SINT32& ar_sResult, UINT32& r_uValue, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveUINT32(r_uValue, a_pClient); return ar_sResult; } // send and receive PChar SINT32 sendPChar(CASocket* a_pClient, UINT8* a_uChar) { if ((a_pClient == NULL) || (a_uChar == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uCLength = 0; uCLength = strlen((char*)a_uChar); sendUINT32(result, a_pClient, uCLength); if (result == E_SUCCESS) result = a_pClient->sendFully(a_uChar, uCLength); return result; } SINT32 receivePChar(UINT8** r_uChar, CASocket* a_pClient) { if ((a_pClient == NULL) || (r_uChar == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uCLength = 0; if (*r_uChar != NULL) delete[] *r_uChar; receiveUINT32(result, uCLength, a_pClient); if (result == E_SUCCESS) if ((*r_uChar = new UINT8[uCLength + 1]) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) result = a_pClient->receiveFully(*r_uChar, uCLength); if (result == E_SUCCESS) (*r_uChar)[uCLength] = 0; return result; } SINT32 sendPChar(SINT32& ar_sResult, CASocket* a_pClient, UINT8* a_uChar) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendPChar(a_pClient, a_uChar); return ar_sResult; } SINT32 receivePChar(SINT32& ar_sResult, UINT8** r_uChar, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receivePChar(r_uChar, a_pClient); return ar_sResult; } // send and receive UINT8* SINT32 sendUINT8Arr(CASocket* a_pClient, UINT32 a_uSize, UINT8* a_uArr) { if ((a_pClient == NULL) || (a_uArr == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; sendUINT32(result, a_pClient, a_uSize); if (result == E_SUCCESS) result = a_pClient->sendFully(a_uArr, a_uSize); return result; } SINT32 receiveUINT8Arr(UINT32& r_uSize, UINT8** r_uArr, CASocket* a_pClient) { if ((a_pClient == NULL) || (r_uArr == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; if (*r_uArr != NULL) delete[] *r_uArr; receiveUINT32(result, r_uSize, a_pClient); if (result == E_SUCCESS) if ((*r_uArr = new UINT8[r_uSize]) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) result = a_pClient->receiveFully(*r_uArr, r_uSize); return result; } SINT32 sendUINT8Arr(SINT32& ar_sResult, CASocket* a_pClient, UINT32 a_uSize, UINT8* a_uArr) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendUINT8Arr(a_pClient, a_uSize, a_uArr); return ar_sResult; } SINT32 receiveUINT8Arr(SINT32& ar_sResult, UINT32& r_uSize, UINT8** r_uArr, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveUINT8Arr(r_uSize, r_uArr, a_pClient); return ar_sResult; } // send and receive BN SINT32 sendBN(CASocket* a_pClient, BIGNUM* a_bn) { if ((a_pClient == NULL) || (a_bn == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uSize = 0; UINT8* uBN = NULL; uSize = BN_num_bytes(a_bn); if ((uBN = new UINT8[uSize]) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) if (BN_bn2bin(a_bn, (unsigned char*)uBN) != uSize) result = E_UNKNOWN; sendUINT8Arr(result, a_pClient, uSize, uBN); delete[] uBN; return result; /*SINT32 result = E_SUCCESS; UINT8* uC = NULL; if ((uC = (UINT8*)BN_bn2hex(a_bn)) == NULL) result = E_UNKNOWN; sendPChar(result, a_pClient, uC); return result;*/ } SINT32 receiveBN(BIGNUM** r_bn, CASocket* a_pClient) { if ((r_bn == NULL) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uSize = 0; UINT8* uBN = NULL; if (*r_bn == NULL) { if ((*r_bn = BN_new()) == NULL) result = E_UNKNOWN; else BN_init(*r_bn); } receiveUINT8Arr(result, uSize, &uBN, a_pClient); if (result == E_SUCCESS) if (BN_bin2bn((unsigned char*)uBN, uSize, *r_bn) == NULL) result = E_UNKNOWN; delete[] uBN; return result; /*SINT32 result = E_SUCCESS; UINT8* uC = NULL; receivePChar(result, &uC, a_pClient); if (result == E_SUCCESS) if (BN_hex2bn(r_bn, (char*)uC) == 0) result = E_UNKNOWN; if (uC != NULL) delete[] uC; return result;*/ } SINT32 sendBN(SINT32& ar_sResult, CASocket* a_pClient, BIGNUM* a_bn) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendBN(a_pClient, a_bn); return ar_sResult; } SINT32 receiveBN(SINT32& ar_sResult, BIGNUM** r_bn, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveBN(r_bn, a_pClient); return ar_sResult; } // send and receive signed BN SINT32 sendSignedBN(ELGAMAL* a_elSignKey, CASocket* a_pClient, BIGNUM* a_bn) { if ((ELGAMAL_isValidPrivateKey(a_elSignKey) == 0) || (a_pClient == NULL) || (a_bn == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM* bnSignS = NULL; BIGNUM* bnSignK = NULL; if (ELGAMAL_sign(&bnSignS, &bnSignK, a_elSignKey, a_bn) == 0) result = E_UNKNOWN; sendBN(result, a_pClient, a_bn); sendBN(result, a_pClient, bnSignS); sendBN(result, a_pClient, bnSignK); if (bnSignS != NULL) BN_free(bnSignS); if (bnSignK != NULL) BN_free(bnSignK); return result; } SINT32 receiveSignedBN(BIGNUM** r_bn, ELGAMAL* a_elTestKey, CASocket* a_pClient) { if ((r_bn == NULL) || (ELGAMAL_isValidPublicKey(a_elTestKey) == 0) || (a_pClient == NULL)) return E_UNKNOWN; if (*r_bn != NULL) { BN_free(*r_bn); *r_bn = NULL; } SINT32 result = E_SUCCESS; BIGNUM* bnSignS = NULL; BIGNUM* bnSignK = NULL; receiveBN(result, r_bn, a_pClient); receiveBN(result, &bnSignS, a_pClient); receiveBN(result, &bnSignK, a_pClient); if (result == E_SUCCESS) if (ELGAMAL_test_signature(a_elTestKey, *r_bn, bnSignS, bnSignK) == 0) result = E_UNKNOWN; if (bnSignS != NULL) BN_free(bnSignS); if (bnSignK != NULL) BN_free(bnSignK); return result; } SINT32 sendSignedBN(SINT32& ar_sResult, ELGAMAL* a_elSignKey, CASocket* a_pClient, BIGNUM* a_bn) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendSignedBN(a_elSignKey, a_pClient, a_bn); return ar_sResult; } SINT32 receiveSignedBN(SINT32& ar_sResult, BIGNUM** r_bn, ELGAMAL* a_elTestKey, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveSignedBN(r_bn, a_elTestKey, a_pClient); return ar_sResult; } // send and receive encrypted public key SINT32 sendEncSignedBN(ELGAMAL* a_elSignKey, ELGAMAL* a_elEncKey, CASocket* a_pClient, BIGNUM* a_bn) { if ((ELGAMAL_isValidPrivateKey(a_elSignKey) == 0) || (a_pClient == NULL) || (ELGAMAL_isValidPublicKey(a_elSignKey) == 0) || (a_bn == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM** vBNEnc = NULL; if ((vBNEnc = new BIGNUM*[2]) == NULL) result = E_UNKNOWN; else { vBNEnc[0] = NULL; // enc A vBNEnc[1] = NULL; // enc B } if (result == E_SUCCESS) if (ELGAMAL_encrypt(&(vBNEnc[0]), &(vBNEnc[1]), a_elEncKey, a_bn) == 0) result = E_UNKNOWN; sendSignedBNArray(result, a_elSignKey, a_pClient, 2, vBNEnc); if (vBNEnc != NULL) { if (vBNEnc[0] != NULL) BN_free(vBNEnc[0]); if (vBNEnc[1] != NULL) BN_free(vBNEnc[1]); } delete[] vBNEnc; return result; } SINT32 receiveEncSignedBN(BIGNUM** r_bn, ELGAMAL* a_elTestKey, ELGAMAL* a_elDecryptKey, CASocket* a_pClient) { if ((ELGAMAL_isValidPublicKey(a_elTestKey) == 0) || (r_bn == NULL) || (ELGAMAL_isValidPrivateKey(a_elDecryptKey) == 0) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM** vBNEnc = NULL; UINT32 uLength = 0; receiveSignedBNArray(result, uLength, &vBNEnc, a_elTestKey, a_pClient); if (uLength != 2) result = E_UNKNOWN; if (result == E_SUCCESS) if (ELGAMAL_decrypt(r_bn, a_elDecryptKey, vBNEnc[0], vBNEnc[1]) == 0) result = E_UNKNOWN; for (UINT32 i = 0; (i < uLength) && (vBNEnc != NULL); i++) if (vBNEnc[i] != NULL) BN_free(vBNEnc[i]); delete[] vBNEnc; return result; } SINT32 sendEncSignedBN(SINT32& ar_sResult, ELGAMAL* a_elSignKey, ELGAMAL* a_elEncKey, CASocket* a_pClient, BIGNUM* a_bn) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendEncSignedBN(a_elSignKey, a_elEncKey, a_pClient, a_bn); return ar_sResult; } SINT32 receiveEncSignedBN(SINT32& ar_sResult, BIGNUM** r_bn, ELGAMAL* a_elTestKey, ELGAMAL* a_elDecryptKey, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveEncSignedBN(r_bn, a_elTestKey, a_elDecryptKey, a_pClient); return ar_sResult; } // send and receive public key SINT32 sendPublicKey(CASocket* a_pClient, ELGAMAL* a_elKey) { if ((a_pClient == NULL) || (ELGAMAL_isValidPublicKey(a_elKey) == 0)) return E_UNKNOWN; SINT32 result = E_SUCCESS; sendBN(result, a_pClient, a_elKey->p); sendBN(result, a_pClient, a_elKey->pm1); sendBN(result, a_pClient, a_elKey->q); sendBN(result, a_pClient, a_elKey->g); sendBN(result, a_pClient, a_elKey->y); return result; } SINT32 receivePublicKey(ELGAMAL** r_elKey, CASocket* a_pClient) { if ((a_pClient == NULL) || (r_elKey == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; if (*r_elKey != NULL) ELGAMAL_free(*r_elKey); *r_elKey = (ELGAMAL*)OPENSSL_malloc(sizeof(ELGAMAL)); memset(*r_elKey, 0, sizeof(ELGAMAL)); receiveBN(result, &(*r_elKey)->p, a_pClient); receiveBN(result, &(*r_elKey)->pm1, a_pClient); receiveBN(result, &(*r_elKey)->q, a_pClient); receiveBN(result, &(*r_elKey)->g, a_pClient); receiveBN(result, &(*r_elKey)->y, a_pClient); if (result == E_SUCCESS) { if (((*r_elKey)->x = BN_new()) == NULL) result = E_UNKNOWN; else { BN_init((*r_elKey)->x); BN_zero((*r_elKey)->x); } } return result; } SINT32 sendPublicKey(SINT32& ar_sResult, CASocket* a_pClient, ELGAMAL* a_elKey) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendPublicKey(a_pClient, a_elKey); return ar_sResult; } SINT32 receivePublicKey(SINT32& ar_sResult, ELGAMAL** r_elKey, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receivePublicKey(r_elKey, a_pClient); return ar_sResult; } // send and receive signed Public keys SINT32 sendSignedPublicKey(ELGAMAL* a_elSignKey, CASocket* a_pClient, ELGAMAL* a_elKey) { if ((ELGAMAL_isValidPrivateKey(a_elSignKey) == 0) || (a_pClient == NULL) || (ELGAMAL_isValidPublicKey(a_elKey) == 0)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM** bnArr = NULL; if ((bnArr = new BIGNUM*[5]) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) { bnArr[0] = a_elKey->p; bnArr[1] = a_elKey->pm1; bnArr[2] = a_elKey->q; bnArr[3] = a_elKey->g; bnArr[4] = a_elKey->y; } sendSignedBNArray(result, a_elSignKey, a_pClient, 5, bnArr); delete[] bnArr; return result; } SINT32 receiveSignedPublicKey(ELGAMAL** r_elKey, ELGAMAL* a_elTestKey, CASocket* a_pClient) { if ((ELGAMAL_isValidPublicKey(a_elTestKey) == 0) || (a_pClient == NULL) || (*r_elKey != NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM** bnArr = NULL; UINT32 uArrLength = 0; if ((*r_elKey = (ELGAMAL*)OPENSSL_malloc(sizeof(ELGAMAL))) == NULL) result = E_SUCCESS; receiveSignedBNArray(result, uArrLength, &bnArr, a_elTestKey, a_pClient); if (result == E_SUCCESS) { (*r_elKey)->p = bnArr[0]; (*r_elKey)->pm1 = bnArr[1]; (*r_elKey)->q = bnArr[2]; (*r_elKey)->g = bnArr[3]; (*r_elKey)->y = bnArr[4]; if (((*r_elKey)->x = BN_new()) == NULL) result = E_UNKNOWN; else { BN_init((*r_elKey)->x); BN_zero((*r_elKey)->x); } } delete[] bnArr; return result; } SINT32 sendSignedPublicKey(SINT32& ar_sResult, ELGAMAL* a_elSignKey, CASocket* a_pClient, ELGAMAL* a_elKey) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendSignedPublicKey(a_elSignKey, a_pClient, a_elKey); return ar_sResult; } SINT32 receiveSignedPublicKey(SINT32& ar_sResult, ELGAMAL** r_elKey, ELGAMAL* a_elTestKey, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveSignedPublicKey(r_elKey, a_elTestKey, a_pClient); return ar_sResult; } // send and receive BN arrays SINT32 sendSignedBNArray(ELGAMAL* a_elSignKey, CASocket* a_pClient, UINT32 a_uBNArrLength, BIGNUM** a_bnArr) { if ((ELGAMAL_isValidPrivateKey(a_elSignKey) == 0) || (a_pClient == NULL) || (a_bnArr == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT8* uBNArr = NULL; UINT32 uSize = 0; UINT8* uHash = NULL; BIGNUM* bnHash = NULL; BIGNUM* bnSignS = NULL; BIGNUM* bnSignK = NULL; if ((uHash = new UINT8[20]) == NULL) result = E_UNKNOWN; if ((bnHash = BN_new()) == NULL) result = E_UNKNOWN; else BN_init(bnHash); BN_bnArr2UINT8Arr(result, uSize, &uBNArr, a_uBNArrLength, a_bnArr); if (result == E_SUCCESS) SHA1((unsigned char*)uBNArr, uSize, (unsigned char*)uHash); // transform Hash-Value into BIGNUM for sign if (result == E_SUCCESS) if (BN_bin2bn((unsigned char*)uHash, 20, bnHash) == NULL) result = E_UNKNOWN; bnSignS = bnSignK = NULL; if (result == E_SUCCESS) if (ELGAMAL_sign(&bnSignS, &bnSignK, a_elSignKey, bnHash) == 0) result = E_UNKNOWN; // send array sendUINT32(result, a_pClient, a_uBNArrLength); for (UINT32 i = 0; (i < a_uBNArrLength) && (result == E_SUCCESS); i++) result = sendBN(a_pClient, a_bnArr[i]); // sendBN(result, a_pClient, bnHash); sendBN(result, a_pClient, bnSignS); sendBN(result, a_pClient, bnSignK); if (bnSignS != NULL) BN_free(bnSignS); if (bnSignK != NULL) BN_free(bnSignK); if (bnHash != NULL) BN_free(bnHash); delete[] uHash; delete[] uBNArr; return result; /* SINT32 result = E_SUCCESS; UINT8* uC = NULL; UINT8** uBNChar = NULL; BIGNUM* bnHash = NULL; BIGNUM* bnSignS = NULL; BIGNUM* bnSignK = NULL; UINT8* upHash = NULL; BN_bnArr2pCharArr(result, &uBNChar, a_uBNArrLength, a_bnArr); pCharArr2pChar(result, &uC, a_uBNArrLength, uBNChar); if ((upHash = new UINT8[20]) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) { SHA1((unsigned char*)uC, strlen((char*)uC), (unsigned char*)upHash); if ((bnHash = BN_new()) == NULL) result = E_UNKNOWN; else { BN_init(bnHash); BN_rand(bnHash, 160, 1, 0); memset(bnHash->d, 0, bnHash->dmax * sizeof(BN_ULONG)); memcpy(bnHash->d, upHash, 20); } } bnSignS = bnSignK = NULL; if (result == E_SUCCESS) if (ELGAMAL_sign(&bnSignS, &bnSignK, a_elSignKey, bnHash) == 0) result = E_UNKNOWN; // send array size sendUINT32(result, a_pClient, a_uBNArrLength); // send array for (UINT32 i = 0; (i < a_uBNArrLength) && (result == E_SUCCESS); i++) sendPChar(result, a_pClient, uBNChar[i]); // send hash sendBN(result, a_pClient, bnHash); sendBN(result, a_pClient, bnSignS); sendBN(result, a_pClient, bnSignK); for (UINT32 i = 0; (i < a_uBNArrLength) && (uBNChar != NULL); i++) delete[] uBNChar[i]; delete[] uBNChar; if (bnHash != NULL) BN_free(bnHash); if (bnSignS != NULL) BN_free(bnSignS); if (bnSignK != NULL) BN_free(bnSignK); delete[] upHash; delete[] uC; return result;*/ } SINT32 receiveSignedBNArray(UINT32& r_uBNArrLength, BIGNUM*** r_bnArr, ELGAMAL* a_elTestKey, CASocket* a_pClient) { if ((*r_bnArr != NULL) || (ELGAMAL_isValidPublicKey(a_elTestKey) == 0) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT8* uBNArr = NULL; UINT32 uSize = 0; UINT8* uHash = NULL; BIGNUM* bnHash = NULL; BIGNUM* bnSignS = NULL; BIGNUM* bnSignK = NULL; if ((uHash = new UINT8[20]) == NULL) result = E_UNKNOWN; if ((bnHash = BN_new()) == NULL) result = E_UNKNOWN; else BN_init(bnHash); receiveUINT32(result, r_uBNArrLength, a_pClient); if (result == E_SUCCESS) if ((*r_bnArr = new BIGNUM*[r_uBNArrLength]) == NULL) result = E_UNKNOWN; // receive array for (UINT32 i = 0; (i < r_uBNArrLength) && (result == E_SUCCESS); i++) { (*r_bnArr)[i] = NULL; result = receiveBN(&((*r_bnArr)[i]), a_pClient); } // receive signature receiveBN(result, &bnSignS, a_pClient); receiveBN(result, &bnSignK, a_pClient); BN_bnArr2UINT8Arr(result, uSize, &uBNArr, r_uBNArrLength, *r_bnArr); if (result == E_SUCCESS) SHA1((unsigned char*)uBNArr, uSize, (unsigned char*)uHash); // transform Hash-Value into BIGNUM for sign if (result == E_SUCCESS) if (BN_bin2bn((unsigned char*)uHash, 20, bnHash) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) if (ELGAMAL_test_signature(a_elTestKey, bnHash, bnSignS, bnSignK) == 0) result = E_UNKNOWN; delete[] uBNArr; delete[] uHash; if (bnHash != NULL) BN_free(bnHash); if (bnSignS != NULL) BN_free(bnSignS); if (bnSignK != NULL) BN_free(bnSignK); return result; /*SINT32 result = E_SUCCESS; UINT8** uBNChar = NULL; UINT8* uC = NULL; BIGNUM* bnHash = NULL; BIGNUM* bnSignS = NULL; BIGNUM* bnSignK = NULL; UINT8* upHash = NULL; receiveUINT32(result, r_uBNArrLength, a_pClient); if ((uBNChar = new (UINT8*)[r_uBNArrLength]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < r_uBNArrLength; i++) uBNChar[i] = NULL; for (UINT32 i = 0; (i < r_uBNArrLength) && (result == E_SUCCESS); i++) receivePChar(result, &(uBNChar[i]), a_pClient); receiveBN(result, &bnHash, a_pClient); receiveBN(result, &bnSignS, a_pClient); receiveBN(result, &bnSignK, a_pClient); pCharArr2pChar(result, &uC, r_uBNArrLength, uBNChar); if ((upHash = new UINT8[20]) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) { SHA1((unsigned char*)uC, strlen((char*)uC), (unsigned char*)upHash); for (UINT32 i = 0; (i < 20) && (result == E_SUCCESS); i++) if (upHash[i] != ((UINT8*)bnHash->d)[i]) result = E_UNKNOWN; } if (result == E_SUCCESS) if (ELGAMAL_test_signature(a_elTestKey, bnHash, bnSignS, bnSignK) == 0) result = E_UNKNOWN; BN_pCharArr2bnArr(result, r_bnArr, r_uBNArrLength, uBNChar); for (UINT32 i = 0; (i < r_uBNArrLength) && (uBNChar != NULL); i++) delete[] uBNChar[i]; delete[] uBNChar; delete[] uC; if (bnHash != NULL) BN_free(bnHash); if (bnSignS != NULL) BN_free(bnSignS); if (bnSignK != NULL) BN_free(bnSignK); delete[] upHash; return result;*/ } SINT32 sendSignedBNArray(SINT32& ar_sResult, ELGAMAL* a_elSignKey, CASocket* a_pClient, UINT32 a_uBNArrLength, BIGNUM** a_bnArr) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = sendSignedBNArray(a_elSignKey, a_pClient, a_uBNArrLength, a_bnArr); return ar_sResult; } SINT32 receiveSignedBNArray(SINT32& ar_sResult, UINT32& r_uBNArrLength, BIGNUM*** r_bnArr, ELGAMAL* a_elTestKey, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = receiveSignedBNArray(r_uBNArrLength, r_bnArr, a_elTestKey, a_pClient); return ar_sResult; } // normal used functions SINT32 BN_bnArr2pCharArr(UINT8*** r_uPCharArray, UINT32 a_bnArrSize, BIGNUM** a_bnArr) { if ((r_uPCharArray == NULL) || (a_bnArr == NULL) || (*r_uPCharArray != NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; if ((*r_uPCharArray = new UINT8*[a_bnArrSize]) == NULL) result = E_UNKNOWN; for (UINT32 i = 0; (i < a_bnArrSize) && (result == E_SUCCESS); i++) { if (a_bnArr[i] == NULL) { result = E_UNKNOWN; continue; } if (((*r_uPCharArray)[i] = (UINT8*)BN_bn2hex(a_bnArr[i])) == NULL) result = E_UNKNOWN; } return result; } SINT32 BN_bnArr2pCharArr(SINT32& ar_sResult, UINT8*** r_uPCharArray, UINT32 a_bnArrSize, BIGNUM** a_bnArr) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = BN_bnArr2pCharArr(r_uPCharArray, a_bnArrSize, a_bnArr); return ar_sResult; } SINT32 BN_pCharArr2bnArr(BIGNUM*** r_bnArr, UINT32 a_bnArrSize, UINT8** a_uPChar) { if ((*r_bnArr != NULL) || (a_uPChar == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; if ((*r_bnArr = new BIGNUM*[a_bnArrSize]) == NULL) result = E_UNKNOWN; for (UINT32 i = 0; (i < a_bnArrSize) && (result == E_SUCCESS); i++) { (*r_bnArr)[i] = NULL; if (BN_hex2bn(&((*r_bnArr)[i]), (char*)a_uPChar[i]) == 0) { (*r_bnArr)[i] = NULL; result = E_UNKNOWN; } } if ((result != E_SUCCESS) && (*r_bnArr != NULL)) { for (UINT32 i = 0; i < a_bnArrSize; i++) if ((*r_bnArr)[i] != NULL) BN_clear_free((*r_bnArr)[i]); delete[] *r_bnArr; *r_bnArr = NULL; } return result; } SINT32 BN_pCharArr2bnArr(SINT32& ar_sResult, BIGNUM*** r_bnArr, UINT32 a_bnArrSize, UINT8** a_uPChar) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = BN_pCharArr2bnArr(r_bnArr, a_bnArrSize, a_uPChar); return ar_sResult; } SINT32 pCharArr2pChar(UINT8** r_uPChar, UINT32 a_uArrSize, UINT8** a_uPCharArr) { if ((r_uPChar == NULL) || (a_uPCharArr == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uCLength = 0; UINT32 uCOffset = 0; UINT32 uLen = 0; if (*r_uPChar != NULL) delete[] *r_uPChar; for (UINT32 i = 0; i < a_uArrSize; i++) uCLength += strlen((char*)a_uPCharArr[i]); if ((*r_uPChar = new UINT8[uCLength + 1]) == NULL) result = E_UNKNOWN; uCOffset = 0; for (UINT32 i = 0; (i < a_uArrSize) && (result == E_SUCCESS); i++) { uLen = strlen((char*)a_uPCharArr[i]); memcpy(*r_uPChar + uCOffset, a_uPCharArr[i], uLen); uCOffset += uLen; } if (result == E_SUCCESS) (*r_uPChar)[uCLength] = 0; else delete[] *r_uPChar; return result; } SINT32 pCharArr2pChar(SINT32& ar_sResult, UINT8** r_uPChar, UINT32 a_uArrSize, UINT8** a_uPCharArr) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = pCharArr2pChar(r_uPChar, a_uArrSize, a_uPCharArr); return ar_sResult; } SINT32 BN_bnArr2UINT8Arr(UINT32& r_uSize, UINT8** r_uArr, UINT32 a_uBNArrSize, BIGNUM** a_bnArr) { if ((r_uArr == NULL) || (a_bnArr == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; UINT32 uOffset = 0; if (*r_uArr != NULL) delete[] *r_uArr; r_uSize = 0; for (UINT32 i = 0; (i < a_uBNArrSize) && (result == E_SUCCESS); i++) { if (a_bnArr[i] == NULL) result = E_UNKNOWN; else r_uSize += BN_num_bytes(a_bnArr[i]); } if ((*r_uArr = new UINT8[r_uSize]) == NULL) result = E_UNKNOWN; uOffset = 0; for (UINT32 i = 0; (i < a_uBNArrSize) && (result == E_SUCCESS); i++) { BN_bn2bin(a_bnArr[i], ((unsigned char*)*r_uArr) + uOffset); uOffset += BN_num_bytes(a_bnArr[i]); } if (result != E_SUCCESS) { delete[] *r_uArr; *r_uArr = NULL; } return result; } SINT32 BN_bnArr2UINT8Arr(SINT32& ar_sResult, UINT32& r_uSize, UINT8** r_uArr, UINT32 a_uBNArrSize, BIGNUM** a_bnArr) { if (ar_sResult != E_SUCCESS) return ar_sResult; ar_sResult = BN_bnArr2UINT8Arr(r_uSize, r_uArr, a_uBNArrSize, a_bnArr); return ar_sResult; } anon-proxy-00.05.38+20081230/FlashMix/CAFlashMix.cpp0000644000175000017500000021221410170075440020052 0ustar daviddavid#include "../StdAfx.h" #include "CAFlashMIX.hpp" //#include //#include void logBN(char* a_cFormatStr, BIGNUM* a_bn) { char* c = BN_bn2dec(a_bn); CAMsg::printMsg(LOG_DEBUG, a_cFormatStr, c); OPENSSL_free(c); } void logBNArr(char* a_cFormatStr, int a_i, BIGNUM* a_bn) { char* c = BN_bn2dec(a_bn); CAMsg::printMsg(LOG_DEBUG, a_cFormatStr, a_i, c); OPENSSL_free(c); }/**/ CAFlashMIX::CAFlashMIX( UINT8* a_uLocalIP, UINT32 a_uPort, UINT32 a_uPortKeyShare, UINT32 a_uPortDummy, UINT32 a_uPortBlind, UINT32 a_uPortBlindOK, UINT8* a_uBBIp, UINT32 a_uBBPort):CAMainThread(a_uPort, handleRequest) { m_uLocalIP = (UINT8*)strdup((char*)a_uLocalIP); m_uPortKeyShare = a_uPortKeyShare; m_uPortDummy = a_uPortDummy; m_uPortBlind = a_uPortBlind; m_uPortDecrypt = a_uPortBlindOK; m_elBBSignKey = NULL; m_elBBEncKey = NULL; m_elSignKey = NULL; m_elEncKey = NULL; m_elGroupKey = NULL; if ((m_pAddrBB = new CASocketAddrINet()) != NULL) m_pAddrBB->setAddr(a_uBBIp, a_uBBPort); m_vMIXData = NULL; m_pMutexMIXData = new CAMutex(); m_elGroupKey = NULL; CAMsg::init(); } CAFlashMIX::~CAFlashMIX() { stop(); join(); logout(); ELGAMAL_free(m_elSignKey); ELGAMAL_free(m_elEncKey); ELGAMAL_free(m_elGroupKey); ELGAMAL_free(m_elBBSignKey); ELGAMAL_free(m_elBBEncKey); clearMIXList(m_pMutexMIXData, m_uMIXCnt, m_vMIXData); delete m_pMutexMIXData; delete m_pAddrBB; free(m_uLocalIP); } SINT32 CAFlashMIX::init() { SINT32 result = E_SUCCESS; CASocket* pSocket = NULL; UINT32 procRes = PROCESS_UNDEF; if (initSocket(result, &pSocket) == E_SUCCESS) result = pSocket->connect(*m_pAddrBB, 5000, 1); CAMsg::printMsg(LOG_DEBUG, "connection to BulletinBoard: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); sendUINT32(result, pSocket, BB_REQ_INIT_MIX); receiveUINT32(result, m_uKeyLength, pSocket); receiveUINT32(result, m_uMIXCnt, pSocket); receiveUINT32(result, m_uMIXPermCnt, pSocket); receiveUINT32(result, m_uMIXDecryptCnt, pSocket); receivePublicKey(result, &m_elBBSignKey, pSocket); receiveSignedPublicKey(result, &m_elBBEncKey, m_elBBSignKey, pSocket); CAMsg::printMsg(LOG_DEBUG, "BulletinBoard data receive: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); if (result == E_SUCCESS) if ((m_elSignKey = ELGAMAL_generate_key(m_uKeyLength)) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) if ((m_elEncKey = ELGAMAL_generate_key(m_uKeyLength)) == NULL) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "key generation: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); sendPChar(result, pSocket, m_uLocalIP); sendUINT32(result, pSocket, m_uPort); sendUINT32(result, pSocket, m_uPortKeyShare); sendUINT32(result, pSocket, m_uPortDummy); sendUINT32(result, pSocket, m_uPortBlind); sendUINT32(result, pSocket, m_uPortDecrypt); sendPublicKey(result, pSocket, m_elSignKey); sendSignedPublicKey(result, m_elSignKey, pSocket, m_elEncKey); receiveUINT32(result, procRes, pSocket); if ((result == E_SUCCESS) && (procRes == PROCESS_SUCCESS)) CAMsg::printMsg(LOG_DEBUG, "add to BulletinBoard: successfully finished\n"); else CAMsg::printMsg(LOG_DEBUG, "add to BulletinBoard: ERROR\n"); if (pSocket != NULL) pSocket->close(); delete pSocket; return result; } SINT32 CAFlashMIX::logout() { SINT32 result = E_SUCCESS; CASocket* pSocket = NULL; UINT32 procRes = PROCESS_UNDEF; if (initSocket(result, &pSocket) == E_SUCCESS) result = pSocket->connect(*m_pAddrBB, 5000, 1); sendUINT32(result, pSocket, BB_REQ_REMOVE_MIX); sendPChar(result, pSocket, m_uLocalIP); sendUINT32(result, pSocket, m_uPort); receiveUINT32(result, procRes, pSocket); if ((result == E_SUCCESS) && (procRes == PROCESS_SUCCESS)) CAMsg::printMsg(LOG_DEBUG, "remove from BulletinBoard: successfully finished\n"); else CAMsg::printMsg(LOG_DEBUG, "remove from BulletinBoard: ERROR\n"); if (pSocket != NULL) pSocket->close(); delete pSocket; return result; } SINT32 CAFlashMIX::receiveMIXData(SINT32& ar_sResult, CASocket* a_pClient) { if (ar_sResult != E_SUCCESS) return ar_sResult; if (a_pClient == NULL) { ar_sResult = E_UNKNOWN; return ar_sResult; } clearMIXList(m_pMutexMIXData, m_uMIXCnt, m_vMIXData); m_vMIXData = NULL; initMIXList(ar_sResult, &m_vMIXData, m_uMIXCnt); for (UINT32 i = 0; (i < m_uMIXCnt) && (ar_sResult == E_SUCCESS); i++) { MIXDATA* pMIXData = NULL; if ((pMIXData = MIXDATA_new()) == NULL) ar_sResult = E_UNKNOWN; receivePChar(ar_sResult, &(pMIXData->cIP), a_pClient); receiveUINT32(ar_sResult, pMIXData->uMainPort, a_pClient); receiveUINT32(ar_sResult, pMIXData->uPortKeyShare, a_pClient); receiveUINT32(ar_sResult, pMIXData->uPortDummy, a_pClient); receiveUINT32(ar_sResult, pMIXData->uPortBlind, a_pClient); receiveUINT32(ar_sResult, pMIXData->uPortDecrypt, a_pClient); receiveSignedPublicKey(ar_sResult, &(pMIXData->elSignKey), m_elBBSignKey, a_pClient); receiveSignedPublicKey(ar_sResult, &(pMIXData->elEncKey), m_elBBSignKey, a_pClient); if (ar_sResult == E_SUCCESS) ar_sResult = insertToMIXList(m_pMutexMIXData, m_uMIXCnt, m_vMIXData, pMIXData); if ((ar_sResult != E_SUCCESS) && (pMIXData != NULL)) MIXDATA_free(pMIXData); } return ar_sResult; } SINT32 CAFlashMIX::receiveMIXValues(SINT32& ar_sResult, BIGNUM*** r_bnAllF, BIGNUM*** r_bnAllSj, BIGNUM** a_bnF, BIGNUM** a_bnSi) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((r_bnAllF == NULL) || (r_bnAllSj == NULL) || (a_bnF == NULL) || (a_bnSi == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if ((*r_bnAllF != NULL) || (*r_bnAllSj != NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } CASocket* pSocket = NULL; UINT32 uSelfIdx = 0xFFFFFFFF; UINT32 procRes = PROCESS_UNDEF; initBNList(ar_sResult, r_bnAllF, m_uMIXCnt * m_uMIXDecryptCnt); initBNList(ar_sResult, r_bnAllSj, m_uMIXCnt); if ((uSelfIdx = getMIXIdx(m_pMutexMIXData, m_uMIXCnt, m_vMIXData, m_uLocalIP, m_uPort)) >= m_uMIXCnt) ar_sResult = E_UNKNOWN; if (initSocket(ar_sResult, &pSocket) == E_SUCCESS) ar_sResult = pSocket->listen(m_uPortKeyShare); for (UINT32 i = 0; (i < uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { CASocket* pClient = NULL; if ((pClient = new CASocket()) == NULL) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) ar_sResult = pSocket->accept(*pClient); // receive all F values for (UINT32 j = 0; (j < m_uMIXDecryptCnt) && (ar_sResult == E_SUCCESS); j++) receiveSignedBN(ar_sResult, &((*r_bnAllF)[i * m_uMIXDecryptCnt + j]), m_vMIXData[i]->elSignKey, pClient); // receive sj receiveEncSignedBN(ar_sResult, &((*r_bnAllSj)[i]), m_vMIXData[i]->elSignKey, m_elEncKey, pClient); // send all F values for (UINT32 j = 0; (j < m_uMIXDecryptCnt) && (ar_sResult == E_SUCCESS); j++) sendSignedBN(ar_sResult, m_elSignKey, pClient, a_bnF[j]); // send si sendEncSignedBN(ar_sResult, m_elSignKey, m_vMIXData[i]->elEncKey, pClient, a_bnSi[i]); receiveUINT32(ar_sResult, procRes, pClient); if (procRes != PROCESS_SUCCESS) ar_sResult = E_UNKNOWN; if (pClient != NULL) pClient->close(); delete pClient; } if (pSocket != NULL) pSocket->close(); delete pSocket; return ar_sResult; } SINT32 CAFlashMIX::sendMIXValues(SINT32&ar_sResult, BIGNUM*** r_bnAllF, BIGNUM*** r_bnAllSj, BIGNUM** a_bnF, BIGNUM** a_bnSi) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((r_bnAllF == NULL) || (r_bnAllSj == NULL) || (a_bnF == NULL) || (a_bnSi == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if ((*r_bnAllF == NULL) || (*r_bnAllSj == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } CASocket** pSockets = NULL; CASocketAddrINet** pAddrs = NULL; UINT32 uSelfIdx = 0xFFFFFFFF; // init all variables initSocketList(ar_sResult, &pSockets, m_uMIXCnt); initSocketAddrINetList(ar_sResult, &pAddrs, m_uMIXCnt); if ((uSelfIdx = getMIXIdx(m_pMutexMIXData, m_uMIXCnt, m_vMIXData, m_uLocalIP, m_uPort)) >= m_uMIXCnt) ar_sResult = E_UNKNOWN; // send and receive Data for (UINT32 i = uSelfIdx + 1; (i < m_uMIXCnt) && (ar_sResult == E_SUCCESS); i++) { // connect to mixes ar_sResult = pAddrs[i]->setAddr(m_vMIXData[i]->cIP, m_vMIXData[i]->uPortKeyShare); if (ar_sResult == E_SUCCESS) ar_sResult = pSockets[i]->connect(*(pAddrs[i]), 5000, 1); // send all F values for (UINT32 j = 0; (j < m_uMIXDecryptCnt) && (ar_sResult == E_SUCCESS); j++) sendSignedBN(ar_sResult, m_elSignKey, pSockets[i], a_bnF[j]); // send si value sendEncSignedBN(ar_sResult, m_elSignKey, m_vMIXData[i]->elEncKey, pSockets[i], a_bnSi[i]); // receive all F values for (UINT32 j = 0; (j < m_uMIXDecryptCnt) && (ar_sResult == E_SUCCESS); j++) receiveSignedBN(ar_sResult, &((*r_bnAllF)[i * m_uMIXDecryptCnt + j]), m_vMIXData[i]->elSignKey, pSockets[i]); // receive sj value receiveEncSignedBN(ar_sResult, &((*r_bnAllSj)[i]), m_vMIXData[i]->elSignKey, m_elEncKey, pSockets[i]); } // send ready for (UINT32 i = m_uMIXCnt - 1; (i > uSelfIdx); i--) { if (ar_sResult == E_SUCCESS) ar_sResult = sendUINT32(pSockets[i], PROCESS_SUCCESS); else sendUINT32(pSockets[i], PROCESS_ERROR); } // free all Variables clearSocketList(m_uMIXCnt, pSockets); clearSocketAddrINetList(m_uMIXCnt, pAddrs); return ar_sResult; } THREAD_RETURN CAFlashMIX::handleRequest(void* a_req) { CAFlashMIX* ths = (CAFlashMIX*)((UINT32*)a_req)[0]; CASocket* pClient = (CASocket*)((UINT32*)a_req)[1]; UINT32 reqCode = MIX_REQ_UNDEF; delete[] (UINT32*)a_req; if (receiveUINT32(reqCode, pClient) == E_SUCCESS) { switch (reqCode) { case MIX_REQ_KEY_SHARE: startKeyShare(ths, pClient); break; // case MIX_REQ_DUMMY: createDummy(ths, pClient); break; // case MIX_REQ_BLIND: blind(ths, pClient); break; case MIX_REQ_MIX_PROCESS: mixProcess(ths, pClient); break; case MIX_REQ_DECRYPT: decrypt(ths, pClient); break; } } if (pClient != NULL) pClient->close(); delete pClient; THREAD_RETURN_SUCCESS; } SINT32 CAFlashMIX::startKeyShare(CAFlashMIX* a_ths, CASocket* a_pClient) { if ((a_ths == NULL) || (a_pClient == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM* bnTmp = NULL; BIGNUM* bnX = NULL; BIGNUM* bnY = NULL; BN_CTX* ctx = NULL; BIGNUM** f = NULL; // the polynom BIGNUM** vBNF = NULL; // the F values Fij = g^fij BIGNUM** vBNsj = NULL; // the Values fi(j) UINT32 uSelfIdx = 0xFFFFFFFF; BIGNUM** vBNAllF = NULL; // the F values of all mixes BIGNUM** vBNAllsj = NULL; // the values fi(j) of the mixes (MIXCnt) UINT32 procRes = PROCESS_UNDEF; CAMsg::printMsg(LOG_DEBUG, "key shareing started\n"); // init all variables initBN(result, &bnX); initBN(result, &bnTmp); initCTX(result, &ctx); a_ths->receiveMIXData(result, a_pClient); CAMsg::printMsg(LOG_DEBUG, "mix data receive: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // receive public group key (y is not valid) ELGAMAL_free(a_ths->m_elGroupKey); a_ths->m_elGroupKey = NULL; receiveSignedPublicKey(result, &(a_ths->m_elGroupKey), a_ths->m_elBBSignKey, a_pClient); // calc secret if (result == E_SUCCESS) if (BN_rand(bnX, a_ths->m_uKeyLength - 1, -1, 1) == 0) result = E_UNKNOWN; while ((BN_cmp(bnX, a_ths->m_elGroupKey->q) >= 0) && (result == E_SUCCESS)) if (BN_rand(bnX, a_ths->m_uKeyLength - 1, -1, 1) == 0) result = E_UNKNOWN; if (result == E_SUCCESS) if (BN_mod_exp(bnTmp, a_ths->m_elGroupKey->g, bnX, a_ths->m_elGroupKey->p, ctx) == 0) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "g^x calc: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // send g exp x sendSignedBN(result, a_ths->m_elSignKey, a_pClient, bnTmp); // receive group y if (receiveSignedBN(result, &bnY, a_ths->m_elBBSignKey, a_pClient) == E_SUCCESS) { if (a_ths->m_elGroupKey->y != NULL) BN_free(a_ths->m_elGroupKey->y); a_ths->m_elGroupKey->y = bnY; } else if (bnY != NULL) BN_free(bnY); CAMsg::printMsg(LOG_DEBUG, "y receive: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // choose polynom if (result == E_SUCCESS) if (ELGAMAL_choose_polynom(&f, a_ths->m_uMIXDecryptCnt - 1, a_ths->m_elGroupKey, bnX) == 0) result = E_UNKNOWN; vBNF = NULL; if (result == E_SUCCESS) if (ELGAMAL_calcF(&vBNF, a_ths->m_elGroupKey, a_ths->m_uMIXDecryptCnt, f) == 0) result = E_UNKNOWN; if (result == E_SUCCESS) if (ELGAMAL_calc_allfij(&vBNsj, a_ths->m_elGroupKey->q, a_ths->m_uMIXCnt, a_ths->m_uMIXDecryptCnt, f) == 0) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "F and s_{ij} calc: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // connect to other mixes if ((uSelfIdx = getMIXIdx(a_ths->m_pMutexMIXData, a_ths->m_uMIXCnt, a_ths->m_vMIXData, a_ths->m_uLocalIP, a_ths->m_uPort)) >= a_ths->m_uMIXCnt) result = E_UNKNOWN; // receive all mix values a_ths->receiveMIXValues(result, &vBNAllF, &vBNAllsj, vBNF, vBNsj); // connect all next mixes a_ths->sendMIXValues(result, &vBNAllF, &vBNAllsj, vBNF, vBNsj); /* for (UINT32 i = 0; i < a_ths->m_uMIXCnt; i++) { if (i == uSelfIdx) continue; logBNArr("all sj = s%d = %s\n", i, vBNAllsj[i]); }/**/ CAMsg::printMsg(LOG_DEBUG, "F and secret s_j send to mixes: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // test the received values for (UINT32 i = 0; (i < a_ths->m_uMIXCnt) && (result == E_SUCCESS); i++) { if (i == uSelfIdx) continue; // the own values are not in this array if (ELGAMAL_testSecret(a_ths->m_elGroupKey, uSelfIdx, vBNAllsj[i], a_ths->m_uMIXDecryptCnt, vBNAllF + i * a_ths->m_uMIXDecryptCnt) == 0) result = E_UNKNOWN; } // test own values if (result == E_SUCCESS) if (ELGAMAL_testSecret(a_ths->m_elGroupKey, uSelfIdx, vBNsj[uSelfIdx], a_ths->m_uMIXDecryptCnt, vBNF) == 0) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "test secret: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); if (bnX != NULL) { BN_clear_free(bnX); bnX = NULL; } if (result == E_SUCCESS) { vBNAllsj[uSelfIdx] = vBNsj[uSelfIdx]; if (ELGAMAL_calcSi(&bnX, a_ths->m_elGroupKey->q, a_ths->m_uMIXCnt, vBNAllsj) == 0) result == E_UNKNOWN; // the value is freed on another place vBNAllsj[uSelfIdx] = NULL; } // check secret for 0 if (result == E_SUCCESS) if (BN_is_zero(bnX) == 1) result = E_UNKNOWN; // save the private key if (result == E_SUCCESS) { if (a_ths->m_elGroupKey->x != NULL) BN_free(a_ths->m_elGroupKey->x); if ((a_ths->m_elGroupKey->x = BN_dup(bnX)) == NULL) result = E_UNKNOWN; } CAMsg::printMsg(LOG_DEBUG, "local secret calc: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // send process state if (result == E_SUCCESS) result = sendUINT32(a_pClient, PROCESS_SUCCESS); else sendUINT32(a_pClient, PROCESS_ERROR); if (result == E_SUCCESS) CAMsg::printMsg(LOG_DEBUG, "key share: successfully finished\n"); else CAMsg::printMsg(LOG_DEBUG, "key share: ERROR\n"); // free all variables clearBNList(a_ths->m_uMIXCnt, vBNAllsj, 1); clearBNList(a_ths->m_uMIXCnt * a_ths->m_uMIXDecryptCnt, vBNAllF, 1); clearBNList(a_ths->m_uMIXCnt, vBNsj, 1); clearBNList(a_ths->m_uMIXDecryptCnt, vBNF, 1); clearBNList(a_ths->m_uMIXDecryptCnt, f, 1); if (bnTmp != NULL) BN_free(bnTmp); if (bnX != NULL) BN_clear_free(bnX); if (ctx != NULL) BN_CTX_free(ctx); return result; } SINT32 CAFlashMIX::createDummies(CAFlashMIX* a_ths, CASocket* a_pClient, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList) { if ((a_ths == NULL) || (a_pClient == NULL) || (a_uPermList == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; BIGNUM** bnDummies = NULL; BN_CTX* ctx = NULL; UINT32 uTmp = 0; // init initCTX(result, &ctx); // receive dummies if (a_uSelfIdx == 0) // receive from BulletinBoard receiveSignedBNArray(result, uTmp, &bnDummies, a_ths->m_elBBSignKey, a_pClient); else receiveSignedBNArray(result, uTmp, &bnDummies, a_ths->m_vMIXData[a_uPermList[a_uSelfIdx - 1]]->elSignKey, a_pPrevMIX); // work on dummies for (UINT32 i = 0; (i < 4) && (result == E_SUCCESS); i++) { BIGNUM* bnTmp = NULL; initBNRand(result, &bnTmp, a_ths->m_uKeyLength); if (result == E_SUCCESS) if (BN_mod_mul(bnDummies[i], bnDummies[i], bnTmp, a_ths->m_elGroupKey->p, ctx) == 0) result = E_UNKNOWN; if (bnTmp != NULL) BN_clear_free(bnTmp); } // send dummies if (a_uSelfIdx == a_ths->m_uMIXPermCnt - 1) // send to BulletinBoard sendSignedBNArray(result, a_ths->m_elSignKey, a_pClient, 4, bnDummies); else sendSignedBNArray(result, a_ths->m_elSignKey, a_pNextMIX, 4, bnDummies); if (ctx != NULL) BN_CTX_free(ctx); clearBNList(4, bnDummies, 1); return result; } SINT32 CAFlashMIX::blindReceiveInpList(SINT32& ar_sResult, UINT32& r_uListSize, BIGNUM*** r_bnInpList, CAFlashMIX* a_ths, CASocket* a_pBBClient, CASocket* a_pPrevMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((r_bnInpList == NULL) || (a_ths == NULL) || (a_pBBClient == NULL) || (a_uPermList == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if (*r_bnInpList != NULL) { ar_sResult = E_UNKNOWN; return ar_sResult; } if ((a_uSelfIdx > 0) && (a_pPrevMIX == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if (a_uSelfIdx == 0) receiveSignedBNArray(ar_sResult, r_uListSize, r_bnInpList, a_ths->m_elBBSignKey, a_pBBClient); else receiveSignedBNArray(ar_sResult, r_uListSize, r_bnInpList, a_ths->m_vMIXData[a_uPermList[a_uSelfIdx - 1]]->elSignKey, a_pPrevMIX); return ar_sResult; } SINT32 CAFlashMIX::blindSendInpList(SINT32& ar_sResult, CAFlashMIX* a_ths, CASocket* a_pBBClient, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList, UINT32 a_uListSize, BIGNUM** a_bnList) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((a_ths == NULL) || (a_pBBClient == NULL) || (a_uPermList == NULL) || (a_bnList == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if ((a_uSelfIdx < a_ths->m_uMIXPermCnt - 1) && (a_pNextMIX == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if (a_uSelfIdx == a_ths->m_uMIXPermCnt - 1) sendSignedBNArray(ar_sResult, a_ths->m_elSignKey, a_pBBClient, a_uListSize, a_bnList); else sendSignedBNArray(ar_sResult, a_ths->m_elSignKey, a_pNextMIX, a_uListSize, a_bnList); return ar_sResult; } SINT32 CAFlashMIX::blindReenc(SINT32& ar_sResult, BIGNUM*** r_bnExp, BIGNUM** ar_bnList, ELGAMAL* a_elGroupKey, UINT32 a_uListSize) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((r_bnExp == NULL) || (ELGAMAL_isValidPublicKey(a_elGroupKey) == 0) || (ar_bnList == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if (*r_bnExp != NULL) return ar_sResult; // work on the input list if (ar_sResult == E_SUCCESS) if (ELGAMAL_gen_exp(r_bnExp, a_elGroupKey, a_uListSize >> 1) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (ELGAMAL_reencrypt(ar_bnList, a_elGroupKey, a_uListSize >> 1, *r_bnExp) == 0) ar_sResult = E_UNKNOWN; return ar_sResult; } SINT32 CAFlashMIX::blind(UINT32* r_uInpListsSize, BIGNUM*** r_bnInpList, UINT32** r_uInpPermLists, BIGNUM*** r_bnExp, CAFlashMIX* a_ths, CASocket* a_pClient, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList) { if ((a_ths == NULL) || (a_pClient == NULL) || (a_uPermList == NULL) || (r_bnExp == NULL) || (r_uInpPermLists == NULL)) return E_UNKNOWN; UINT32 LISTCNT = 4; SINT32 result = E_SUCCESS; for (UINT32 i = 0; (i < LISTCNT) && (result == E_SUCCESS); i++) { r_uInpPermLists[i] = NULL; r_bnInpList[i] = NULL; r_bnExp[i] = NULL; r_uInpListsSize[i] = 0; } for (UINT32 i = 0; (i < LISTCNT) && (result == E_SUCCESS); i++) { blindReceiveInpList(result, r_uInpListsSize[i], &(r_bnInpList[i]), a_ths, a_pClient, a_pPrevMIX, a_uSelfIdx, a_uPermList); blindReenc(result, &(r_bnExp[i]), r_bnInpList[i], a_ths->m_elGroupKey, r_uInpListsSize[i]); createRndList(result, &(r_uInpPermLists[i]), r_uInpListsSize[i] >> 1, r_uInpListsSize[i] >> 1); /* for (UINT32 j = 0; j < r_uInpListsSize[i] >> 1; j++) cout << " " << r_uInpPermLists[i][j]; cout << endl;/**/ /* for (UINT32 j = 0; j < r_uInpListsSize[i] >> 1; j++) { char* c = BN_bn2dec(r_bnExp[i][j]); CAMsg::printMsg(LOG_DEBUG, "used exp: [%d, %d] = %s\n", i, j, c); OPENSSL_free(c); }/**/ permutate(result, r_bnInpList[i], r_uInpListsSize[i], r_uInpPermLists[i]); blindSendInpList(result, a_ths, a_pClient, a_pNextMIX, a_uSelfIdx, a_uPermList, r_uInpListsSize[i], r_bnInpList[i]); } return result; } SINT32 CAFlashMIX::mixProcess(CAFlashMIX* a_ths, CASocket* a_pClient) { if ((a_ths == NULL) || (a_pClient == NULL)) return E_UNKNOWN; UINT32 MIXCNT = a_ths->m_uMIXPermCnt; UINT32 LISTCNT = 2; UINT32 DUMMYCNT = 2; UINT32 REENCCNT = 2; SINT32 result = E_SUCCESS; UINT32 uSelfIdx = 0xFFFFFFFF; UINT32* uPermList = NULL; UINT32 uBlindRes = BLIND_UNDEF; UINT32** uInpPerm = NULL; UINT32* uInpListsSize = NULL; BIGNUM*** bnExp = NULL; BIGNUM*** bnInpList = NULL; CASocket* pSocketNextMIX = NULL; CASocket* pSocketPrevMIX = NULL; CASocketAddrINet* pAddr = NULL; CAMsg::printMsg(LOG_DEBUG, "mix process started\n"); // init variables if ((uPermList = new UINT32[MIXCNT]) == NULL) result = E_UNKNOWN; if ((uInpPerm = new UINT32*[LISTCNT * REENCCNT]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < LISTCNT * REENCCNT; i++) uInpPerm[i] = NULL; if ((uInpListsSize = new UINT32[LISTCNT * REENCCNT]) == NULL) result = E_UNKNOWN; if ((bnExp = new BIGNUM**[LISTCNT * REENCCNT]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < LISTCNT * REENCCNT; i++) bnExp[i] = NULL; if ((bnInpList = new BIGNUM**[LISTCNT * REENCCNT]) == NULL) result = E_UNKNOWN; else for (UINT32 i = 0; i < LISTCNT * REENCCNT; i++) bnInpList[i] = NULL; // wait for selfindex and permutation list receiveUINT32(result, uSelfIdx, a_pClient); for (UINT32 i = 0; (i < a_ths->m_uMIXPermCnt) && (result == E_SUCCESS); i++) receiveUINT32(result, uPermList[i], a_pClient); CAMsg::printMsg(LOG_DEBUG, "permutation list: %s\n", (result == E_SUCCESS) ? "successfully received" : "ERROR on receive"); // connect prev and next mix if (uSelfIdx > 0) { if ((pSocketNextMIX = new CASocket()) == NULL) result = E_UNKNOWN; else result = pSocketNextMIX->listen(a_ths->m_uPortBlind); if ((pSocketPrevMIX = new CASocket()) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) result = pSocketNextMIX->accept(*pSocketPrevMIX); if (pSocketNextMIX != NULL) pSocketNextMIX->close(); delete pSocketNextMIX; pSocketNextMIX = NULL; } // connect to next mixes if (uSelfIdx < a_ths->m_uMIXPermCnt - 1) { if (pSocketNextMIX != NULL) { pSocketNextMIX->close(); delete pSocketNextMIX; pSocketNextMIX = NULL; } initSocket(result, &pSocketNextMIX); MIXDATA* pMIXData = a_ths->m_vMIXData[uPermList[uSelfIdx + 1]]; if (initSocketAddrINet(result, &pAddr) == E_SUCCESS) result = pAddr->setAddr(pMIXData->cIP, pMIXData->uPortBlind); if (result == E_SUCCESS) result = pSocketNextMIX->connect(*pAddr, 5000, 1); } CAMsg::printMsg(LOG_DEBUG, "MIX connection: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // create Dummmy if (result == E_SUCCESS) result = createDummies(a_ths, a_pClient, pSocketPrevMIX, pSocketNextMIX, uSelfIdx, uPermList); CAMsg::printMsg(LOG_DEBUG, "dummy creation: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // blinding if (result == E_SUCCESS) result = blind(uInpListsSize, bnInpList, uInpPerm, bnExp, a_ths, a_pClient, pSocketPrevMIX, pSocketNextMIX, uSelfIdx, uPermList); // wait for blind success receiveUINT32(result, uBlindRes, a_pClient); if ((uBlindRes != BLIND_SUCCESS) && (result == E_SUCCESS)) result = E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "blind: %s\n", (uBlindRes == BLIND_SUCCESS) ? "successfully finished" : "ERROR"); if (result == E_SUCCESS) result = unblind(a_ths, a_pClient, pSocketPrevMIX, pSocketNextMIX, uSelfIdx, uPermList, uInpListsSize, bnInpList, uInpPerm, bnExp); CAMsg::printMsg(LOG_DEBUG, "unblind: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // send unblind result if (result == E_SUCCESS) result = sendUINT32(a_pClient, UNBLIND_SUCCESS); else sendUINT32(a_pClient, UNBLIND_ERROR); // free all variablen for (UINT32 i = 0; (i < LISTCNT * REENCCNT) && (bnInpList != NULL); i++) clearBNList(uInpListsSize[i], bnInpList[i], 1); delete[] bnInpList; for (UINT32 i = 0; (i < LISTCNT * REENCCNT) && (bnExp != NULL); i++) clearBNList(uInpListsSize[i] >> 1, bnExp[i], 1); delete[] bnExp; for (UINT32 i = 0; (i < LISTCNT * REENCCNT) && (uInpPerm != NULL); i++) delete[] uInpPerm[i]; delete[] uInpPerm; delete[] uInpListsSize; if (pSocketNextMIX != NULL) pSocketNextMIX->close(); if (pSocketPrevMIX != NULL) pSocketPrevMIX->close(); delete pSocketNextMIX; delete pSocketPrevMIX; delete pAddr; delete[] uPermList; return result; } SINT32 CAFlashMIX::permutate(SINT32& ar_sResult, BIGNUM** ar_bnList, UINT32 a_uListSize, UINT32* a_uPerm) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((ar_bnList == NULL) || (a_uPerm == NULL)) { ar_sResult E_UNKNOWN; return ar_sResult; } for (UINT32 i = 1; i < (a_uListSize >> 1); i++) { switchEncListElements(a_uListSize, ar_bnList, a_uPerm[0], a_uPerm[i]); } return ar_sResult; } SINT32 CAFlashMIX::unblind(CAFlashMIX* a_ths, CASocket* a_pBB, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList, UINT32* a_uInpListsSize, BIGNUM*** a_bnInpList, UINT32** a_uInpPerm, BIGNUM*** a_bnExp) { if ((a_ths == NULL) || (a_uPermList == NULL) || (a_uInpListsSize == NULL) || (a_pBB == NULL)) return E_UNKNOWN; if ((a_uSelfIdx > 0) && (a_pPrevMIX == NULL)) return E_UNKNOWN; if ((a_uSelfIdx < a_ths->m_uMIXPermCnt - 1) && (a_pNextMIX == NULL)) return E_UNKNOWN; UINT32 MIXCNT = a_ths->m_uMIXPermCnt; UINT32 LISTCNT = 2; UINT32 DUMMYCNT = 2; UINT32 REENCCNT = 2; UINT32 DUMMYLISTSIZE = MIXCNT * LISTCNT * DUMMYCNT * REENCCNT; UINT32 MIXFAC = LISTCNT * DUMMYCNT * REENCCNT; UINT32 LISTFAC = DUMMYCNT * REENCCNT; UINT32 DUMMYFAC = REENCCNT; UINT32 REENCFAC = 1; SINT32 result = E_SUCCESS; UINT32* uDummyPerm = NULL; // linearisized 3 dim array [M][L][D] = [M*LC*DC + L*DC + D] BIGNUM** bnInpList = NULL; BIGNUM** bnFirstListFirstReenc = NULL; BIGNUM** bnSecondListFirstReenc = NULL; BIGNUM** bnFirstListSecondReenc = NULL; BIGNUM** bnSecondListSecondReenc = NULL; UINT32 uInpListSize = 0; BIGNUM** bnDummyExp2ReEnc = NULL; // init if ((uDummyPerm = new UINT32[DUMMYLISTSIZE]) == NULL) result = E_UNKNOWN; // receive input, first reenc and second reenc list receiveSignedBNArray(result, uInpListSize, &bnInpList, a_ths->m_elBBSignKey, a_pBB); receiveSignedBNArray(result, uInpListSize, &bnFirstListFirstReenc, a_ths->m_elBBSignKey, a_pBB); receiveSignedBNArray(result, uInpListSize, &bnSecondListFirstReenc, a_ths->m_elBBSignKey, a_pBB); receiveSignedBNArray(result, uInpListSize, &bnFirstListSecondReenc, a_ths->m_elBBSignKey, a_pBB); receiveSignedBNArray(result, uInpListSize, &bnSecondListSecondReenc, a_ths->m_elBBSignKey, a_pBB); CAMsg::printMsg(LOG_DEBUG, "unblind receive lists: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); unblindSendReceiveDummyData(result, uDummyPerm, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, MIXCNT, LISTCNT, DUMMYCNT, REENCCNT, a_uInpListsSize, a_uInpPerm, (UINT32)0); unblindSendReceiveDummyData(result, uDummyPerm, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, MIXCNT, LISTCNT, DUMMYCNT, REENCCNT, a_uInpListsSize, a_uInpPerm, (UINT32)1); CAMsg::printMsg(LOG_DEBUG, "unblind receive dummy permutations: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); unblindSendReceiveDummyExp2ReEnc(result, &bnDummyExp2ReEnc, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, a_bnExp, uDummyPerm, MIXCNT, LISTCNT, DUMMYCNT, REENCCNT, uInpListSize >> 1); CAMsg::printMsg(LOG_DEBUG, "unblind receive dummy exponents: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); unblindCheck2Dummy(result, a_ths, bnFirstListFirstReenc, bnSecondListFirstReenc, bnFirstListSecondReenc, bnSecondListSecondReenc, uDummyPerm, bnDummyExp2ReEnc, MIXCNT, MIXFAC, LISTFAC, DUMMYFAC, REENCFAC); CAMsg::printMsg(LOG_DEBUG, "unblind check second dummy: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); unblindCheckProd(result, a_ths, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, a_uInpListsSize, bnFirstListFirstReenc, bnSecondListFirstReenc, a_bnInpList, a_bnExp, MIXCNT, LISTCNT, DUMMYCNT, REENCCNT); CAMsg::printMsg(LOG_DEBUG, "unblind check products: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); unblindCheckFirstReEnc(result, a_ths, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, uInpListSize, bnInpList, bnFirstListFirstReenc, bnSecondListFirstReenc, a_uInpPerm, a_bnExp, MIXCNT); CAMsg::printMsg(LOG_DEBUG, "unblind check first reenc: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // send the dummy-positions to bulletinboard // only the last mix sends the positions if (a_uSelfIdx == a_ths->m_uMIXPermCnt - 1) { sendUINT32(result, a_pBB, uDummyPerm[a_uSelfIdx*MIXFAC + 0*LISTFAC + 0*DUMMYFAC + 1*REENCFAC]); sendUINT32(result, a_pBB, uDummyPerm[a_uSelfIdx*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 1*REENCFAC]); } // free all delete[] uDummyPerm; clearBNList(uInpListSize, bnInpList, 1); clearBNList(uInpListSize, bnFirstListFirstReenc, 1); clearBNList(uInpListSize, bnSecondListFirstReenc, 1); clearBNList(uInpListSize, bnFirstListSecondReenc, 1); clearBNList(uInpListSize, bnSecondListSecondReenc, 1); clearBNList(2*MIXCNT, bnDummyExp2ReEnc, 1); return result; } SINT32 CAFlashMIX::unblindSendReceiveDummyData(SINT32& ar_sResult, UINT32* ar_uDummies, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 MIXCNT, UINT32 LISTCNT, UINT32 DUMMYCNT, UINT32 REENCCNT, UINT32* a_uInpPermSize, UINT32** a_uInpPerm, UINT32 a_rReEnc) { if (ar_sResult != E_SUCCESS) return ar_sResult; if (ar_uDummies == NULL) { ar_sResult = E_UNKNOWN; return ar_sResult; } if ((a_uSelfIdx > 0) && (a_pPrevMIX == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } if ((a_uSelfIdx < MIXCNT - 1) && (a_pNextMIX == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } UINT32 MIXFAC = LISTCNT * DUMMYCNT * REENCCNT; UINT32 LISTFAC = DUMMYCNT * REENCCNT; UINT32 DUMMYFAC = REENCCNT; UINT32 REENCFAC = 1; UINT32 DUMMYLISTSIZE = MIXCNT * LISTCNT * DUMMYCNT * REENCCNT; UINT32 uReEnc = 0; if (a_rReEnc != 0) uReEnc = 1; // first MIX init the dummy-list if ((uReEnc == 0) && (a_uSelfIdx == 0)) for (UINT32 i = 0; i < DUMMYLISTSIZE; i++) ar_uDummies[i] = 0xFFFFFFFF; // receive dummy data from prev mix if (a_uSelfIdx > 0) for (UINT32 i = 0; (i < DUMMYLISTSIZE) && (ar_sResult == E_SUCCESS); i++) ar_sResult = receiveUINT32(ar_uDummies[i], a_pPrevMIX); // add own perm data if (a_uSelfIdx == 0) { // list loop for (UINT32 l = 0; (l < LISTCNT) && (ar_sResult == E_SUCCESS); l++) // dummy loop for (UINT32 d = 0; (d < DUMMYCNT) && (ar_sResult == E_SUCCESS); d++) getNextPermElement(ar_sResult, ar_uDummies[a_uSelfIdx*MIXFAC + l*LISTFAC + d*DUMMYFAC + uReEnc*REENCFAC], a_uInpPermSize[l] >> 1, a_uInpPerm[l + uReEnc * 2], (1 - uReEnc) * ((a_uInpPermSize[l] >> 1) - 2 + d) + uReEnc * (ar_uDummies[(MIXCNT - 1)*MIXFAC + l*LISTFAC + d*DUMMYFAC + (1 - uReEnc)*REENCFAC])); } else { // list loop for (UINT32 l = 0; (l < LISTCNT) && (ar_sResult == E_SUCCESS); l++) // dummy loop for (UINT32 d = 0; (d < DUMMYCNT) && (ar_sResult == E_SUCCESS); d++) getNextPermElement(ar_sResult, ar_uDummies[a_uSelfIdx*MIXFAC + l*LISTFAC + d*DUMMYFAC + uReEnc*REENCFAC], a_uInpPermSize[l] >> 1, a_uInpPerm[l + uReEnc * 2], ar_uDummies[(a_uSelfIdx - 1)*MIXFAC + l*LISTFAC + d*DUMMYFAC + uReEnc*REENCFAC]); } if (a_uSelfIdx < MIXCNT - 1) { // send dummy-list to next mix for (UINT32 i = 0; (i < DUMMYLISTSIZE) && (ar_sResult == E_SUCCESS); i++) ar_sResult = sendUINT32(a_pNextMIX, ar_uDummies[i]); // receive dummy-list from next mix for (UINT32 i = 0; (i < DUMMYLISTSIZE) && (ar_sResult == E_SUCCESS); i++) ar_sResult = receiveUINT32(ar_uDummies[i], a_pNextMIX); } // send dummy-list to prev mix if (a_uSelfIdx > 0) for (UINT32 i = 0; (i < DUMMYLISTSIZE) && (ar_sResult == E_SUCCESS); i++) ar_sResult = sendUINT32(a_pPrevMIX, ar_uDummies[i]); return ar_sResult; } SINT32 CAFlashMIX::unblindSendReceiveDummyExp2ReEnc(SINT32& ar_sResult, BIGNUM*** r_bnExp2ReEnc, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, BIGNUM*** a_bnExp, UINT32* a_uDummyPerm, UINT32 MIXCNT, UINT32 LISTCNT, UINT32 DUMMYCNT, UINT32 REENCCNT, UINT32 explistsize) { if (ar_sResult != E_SUCCESS) return ar_sResult; if (*r_bnExp2ReEnc != NULL) { ar_sResult = E_UNKNOWN; return ar_sResult; } UINT32 MIXFAC = LISTCNT * DUMMYCNT * REENCCNT; UINT32 LISTFAC = DUMMYCNT * REENCCNT; UINT32 DUMMYFAC = REENCCNT; UINT32 REENCFAC = 1; if ((*r_bnExp2ReEnc = new BIGNUM*[2*MIXCNT]) == NULL) ar_sResult = E_UNKNOWN; else for (UINT32 i = 0; i < 2*MIXCNT; i++) (*r_bnExp2ReEnc)[i] = NULL; // receive exp from prev mixes if (a_uSelfIdx > 0) for (UINT32 i = 0; (i < a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { receiveBN(ar_sResult, &((*r_bnExp2ReEnc)[2*i]), a_pPrevMIX); receiveBN(ar_sResult, &((*r_bnExp2ReEnc)[2*i + 1]), a_pPrevMIX); } // add own exp if (a_uSelfIdx == 0) { (*r_bnExp2ReEnc)[2*a_uSelfIdx] = BN_dup(a_bnExp[2][a_uDummyPerm[(MIXCNT - 1)*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 0*REENCFAC]]); (*r_bnExp2ReEnc)[2*a_uSelfIdx + 1] = BN_dup(a_bnExp[3][a_uDummyPerm[(MIXCNT - 1)*MIXFAC + 1*LISTFAC + 1*DUMMYFAC + 0*REENCFAC]]); } else { (*r_bnExp2ReEnc)[2*a_uSelfIdx] = BN_dup(a_bnExp[2][a_uDummyPerm[(a_uSelfIdx - 1)*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 1*REENCFAC]]); (*r_bnExp2ReEnc)[2*a_uSelfIdx + 1] = BN_dup(a_bnExp[3][a_uDummyPerm[(a_uSelfIdx - 1)*MIXFAC + 1*LISTFAC + 1*DUMMYFAC + 1*REENCFAC]]); } // send data to next mix if (a_uSelfIdx < MIXCNT - 1) { for (UINT32 i = 0; (i <= a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { sendBN(ar_sResult, a_pNextMIX, (*r_bnExp2ReEnc)[2*i]); sendBN(ar_sResult, a_pNextMIX, (*r_bnExp2ReEnc)[2*i + 1]); } for (UINT32 i = a_uSelfIdx + 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { receiveBN(ar_sResult, &((*r_bnExp2ReEnc)[2*i]), a_pNextMIX); receiveBN(ar_sResult, &((*r_bnExp2ReEnc)[2*i + 1]), a_pNextMIX); } } // send data to prev mix if (a_uSelfIdx > 0) for (UINT32 i = a_uSelfIdx; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { sendBN(ar_sResult, a_pPrevMIX, (*r_bnExp2ReEnc)[2*i]); sendBN(ar_sResult, a_pPrevMIX, (*r_bnExp2ReEnc)[2*i + 1]); } return ar_sResult; } SINT32 CAFlashMIX::switchEncListElements(UINT32 a_uListSize, BIGNUM** ar_bnList, UINT32 a_uMsgIdx1, UINT32 a_uMsgIdx2) { if ((a_uMsgIdx1 >= a_uListSize >> 1) || (a_uMsgIdx2 >= a_uListSize)) return E_UNKNOWN; if (ar_bnList == NULL) return E_UNKNOWN; BIGNUM* bnTmp = ar_bnList[2 * a_uMsgIdx1]; ar_bnList[2 * a_uMsgIdx1] = ar_bnList[2 * a_uMsgIdx2]; ar_bnList[2 * a_uMsgIdx2] = bnTmp; bnTmp = ar_bnList[2 * a_uMsgIdx1 + 1]; ar_bnList[2 * a_uMsgIdx1 + 1] = ar_bnList[2 * a_uMsgIdx2 + 1]; ar_bnList[2 * a_uMsgIdx2 + 1] = bnTmp; return E_SUCCESS; } SINT32 CAFlashMIX::unblindCheck2Dummy(SINT32& ar_sResult, CAFlashMIX* a_ths, BIGNUM** a_bnL0R0, BIGNUM** a_bnL1R0, BIGNUM** a_bnL0R1, BIGNUM** a_bnL1R1, UINT32* a_uDummyPerm, BIGNUM** a_bnDummyExp, UINT32 MIXCNT, UINT32 MIXFAC, UINT32 LISTFAC, UINT32 DUMMYFAC, UINT32 REENCFAC) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((a_bnL0R0 == NULL) || (a_bnL1R0 == NULL) || (a_bnL0R1 == NULL) || (a_bnL1R1 == NULL) || (a_uDummyPerm == NULL) || (a_bnDummyExp == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } // list 0 BIGNUM* bnA = BN_dup(a_bnL0R0[2 * a_uDummyPerm[(MIXCNT - 1)*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 0*REENCFAC]]); BIGNUM* bnB = BN_dup(a_bnL0R0[2 * a_uDummyPerm[(MIXCNT - 1)*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 0*REENCFAC] + 1]); if ((bnA == NULL) || (bnB == NULL)) ar_sResult = E_UNKNOWN; for (UINT32 i = 0; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) if (ELGAMAL_reencrypt(bnA, bnB, a_ths->m_elGroupKey, a_bnDummyExp[2*i]) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnA, a_bnL0R1[2 * a_uDummyPerm[(MIXCNT-1)*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 1*REENCFAC]]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnB, a_bnL0R1[2 * a_uDummyPerm[(MIXCNT-1)*MIXFAC + 0*LISTFAC + 1*DUMMYFAC + 1*REENCFAC] + 1]) != 0) ar_sResult = E_UNKNOWN; BN_free(bnB); bnB = NULL; BN_free(bnA); bnA = NULL; // list 1 bnA = BN_dup(a_bnL1R0[2 * a_uDummyPerm[(MIXCNT - 1)*MIXFAC + 1*LISTFAC + 1*DUMMYFAC + 0*REENCFAC]]); bnB = BN_dup(a_bnL1R0[2 * a_uDummyPerm[(MIXCNT - 1)*MIXFAC + 1*LISTFAC + 1*DUMMYFAC + 0*REENCFAC] + 1]); if ((bnA == NULL) || (bnB == NULL)) ar_sResult = E_UNKNOWN; for (UINT32 i = 0; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) if (ELGAMAL_reencrypt(bnA, bnB, a_ths->m_elGroupKey, a_bnDummyExp[2*i + 1]) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnA, a_bnL1R1[2 * a_uDummyPerm[(MIXCNT-1)*MIXFAC + 1*LISTFAC + 1*DUMMYFAC + 1*REENCFAC]]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnB, a_bnL1R1[2 * a_uDummyPerm[(MIXCNT-1)*MIXFAC + 1*LISTFAC + 1*DUMMYFAC + 1*REENCFAC] + 1]) != 0) ar_sResult = E_UNKNOWN; BN_free(bnB); bnB = NULL; BN_free(bnA); bnA = NULL; return ar_sResult; } SINT32 CAFlashMIX::unblindCheckProd(SINT32& ar_sResult, CAFlashMIX* a_ths, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uInpListsSize, BIGNUM** a_bnInpFirstReEncList, BIGNUM** a_bnInpSecondReEncList, BIGNUM*** a_bnOutLists, BIGNUM*** a_bnExp, UINT32 MIXCNT, UINT32 LISTCNT, UINT32 DUMMYCNT, UINT32 REENCCNT) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((a_uInpListsSize == NULL) || (a_bnOutLists == NULL) || (a_bnExp == NULL) || (a_bnInpFirstReEncList == NULL) || (a_bnInpSecondReEncList == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } BIGNUM** bnProdList = NULL; BIGNUM** bnExpList = NULL; BIGNUM* bnProdInpA0 = NULL; BIGNUM* bnProdInpB0 = NULL; BIGNUM* bnProdInpA1 = NULL; BIGNUM* bnProdInpB1 = NULL; BN_CTX* ctx = NULL; initBNList(ar_sResult, &bnProdList, 4*MIXCNT); initBNList(ar_sResult, &bnExpList, 2*MIXCNT); if ((ctx = BN_CTX_new()) == NULL) ar_sResult = E_UNKNOWN; else BN_CTX_init(ctx); // receive data of prev mixes for (UINT32 i = 0; (i < a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < 4) && (ar_sResult == E_SUCCESS); j++) receiveBN(ar_sResult, &(bnProdList[4 * i + j]), a_pPrevMIX); for (UINT32 j = 0; (j < 2) && (ar_sResult == E_SUCCESS); j++) receiveBN(ar_sResult, &(bnExpList[2 * i + j]), a_pPrevMIX); } // add own data if (ar_sResult == E_SUCCESS) { // data of outputlist BIGNUM* bnProdA0 = BN_new(); BIGNUM* bnProdB0 = BN_new(); BIGNUM* bnProdA1 = BN_new(); BIGNUM* bnProdB1 = BN_new(); BIGNUM* bnSumExp0 = BN_new(); BIGNUM* bnSumExp1 = BN_new(); if ((bnProdA0 == NULL) || (bnProdB0 == NULL) || (bnSumExp0 == NULL) || (bnProdA1 == NULL) || (bnProdB1 == NULL) || (bnSumExp1 == NULL)) ar_sResult = E_UNKNOWN; else { BN_init(bnProdA0); BN_one(bnProdA0); BN_init(bnProdB0); BN_one(bnProdB0); BN_init(bnSumExp0); BN_zero(bnSumExp0); BN_init(bnProdA1); BN_one(bnProdA1); BN_init(bnProdB1); BN_one(bnProdB1); BN_init(bnSumExp1); BN_zero(bnSumExp1); } for (UINT32 i = 0; (i < a_uInpListsSize[0]) && (ar_sResult == E_SUCCESS); i += 2) { if (BN_mod_mul(bnProdA0, bnProdA0, a_bnOutLists[2][i + 0], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; if (BN_mod_mul(bnProdB0, bnProdB0, a_bnOutLists[2][i + 1], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; if (BN_mod_mul(bnProdA1, bnProdA1, a_bnOutLists[3][i + 0], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; if (BN_mod_mul(bnProdB1, bnProdB1, a_bnOutLists[3][i + 1], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; } for (UINT32 i = 0; (i < a_uInpListsSize[0] >> 1) && (ar_sResult == E_SUCCESS); i++) { if (BN_mod_add(bnSumExp0, bnSumExp0, a_bnExp[2][i], a_ths->m_elGroupKey->q, ctx) == 0) ar_sResult == E_UNKNOWN; if (BN_mod_add(bnSumExp1, bnSumExp1, a_bnExp[3][i], a_ths->m_elGroupKey->q, ctx) == 0) ar_sResult == E_UNKNOWN; } if (ar_sResult == E_SUCCESS) { bnProdList[4*a_uSelfIdx + 0] = bnProdA0; bnProdList[4*a_uSelfIdx + 1] = bnProdB0; bnProdList[4*a_uSelfIdx + 2] = bnProdA1; bnProdList[4*a_uSelfIdx + 3] = bnProdB1; bnExpList[2*a_uSelfIdx + 0] = bnSumExp0; bnExpList[2*a_uSelfIdx + 1] = bnSumExp1; } else { if (bnProdA0 != NULL) BN_free(bnProdA0); if (bnProdB0 != NULL) BN_free(bnProdB0); if (bnProdA1 != NULL) BN_free(bnProdA1); if (bnProdB1 != NULL) BN_free(bnProdB1); if (bnSumExp0 != NULL) BN_free(bnSumExp0); if (bnSumExp1 != NULL) BN_free(bnSumExp1); } } if (a_uSelfIdx < MIXCNT - 1) { // send data to next mix for (UINT32 i = 0; (i <= a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < 4) && (ar_sResult == E_SUCCESS); j++) sendBN(ar_sResult, a_pNextMIX, bnProdList[4 * i + j]); for (UINT32 j = 0; (j < 2) && (ar_sResult == E_SUCCESS); j++) sendBN(ar_sResult, a_pNextMIX, bnExpList[2 * i + j]); } // receive data from next mix for (UINT32 i = a_uSelfIdx + 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < 4) && (ar_sResult == E_SUCCESS); j++) receiveBN(ar_sResult, &(bnProdList[4 * i + j]), a_pNextMIX); for (UINT32 j = 0; (j < 2) && (ar_sResult == E_SUCCESS); j++) receiveBN(ar_sResult, &(bnExpList[2 * i + j]), a_pNextMIX); } } // send data to prev mix if (a_uSelfIdx > 0) for (UINT32 i = a_uSelfIdx; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < 4) && (ar_sResult == E_SUCCESS); j++) sendBN(ar_sResult, a_pPrevMIX, bnProdList[4 * i + j]); for (UINT32 j = 0; (j < 2) && (ar_sResult == E_SUCCESS); j++) sendBN(ar_sResult, a_pPrevMIX, bnExpList[2 * i + j]); } // calc the product of inputlist bnProdInpA0 = BN_new(); bnProdInpB0 = BN_new(); bnProdInpA1 = BN_new(); bnProdInpB1 = BN_new(); if ((bnProdInpA0 == NULL) || (bnProdInpB0 == NULL) || (bnProdInpA1 == NULL) || (bnProdInpB1 == NULL)) ar_sResult = E_UNKNOWN; else { BN_init(bnProdInpA0); BN_one(bnProdInpA0); BN_init(bnProdInpB0); BN_one(bnProdInpB0); BN_init(bnProdInpA1); BN_one(bnProdInpA1); BN_init(bnProdInpB1); BN_one(bnProdInpB1); } for (UINT32 i = 0; (i < a_uInpListsSize[0]) && (ar_sResult == E_SUCCESS); i += 2) { if (BN_mod_mul(bnProdInpA0, bnProdInpA0, a_bnInpFirstReEncList[i + 0], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; if (BN_mod_mul(bnProdInpB0, bnProdInpB0, a_bnInpFirstReEncList[i + 1], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; if (BN_mod_mul(bnProdInpA1, bnProdInpA1, a_bnInpSecondReEncList[i + 0], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; if (BN_mod_mul(bnProdInpB1, bnProdInpB1, a_bnInpSecondReEncList[i + 1], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; } // check the first mix data if (ar_sResult == E_SUCCESS) if (ELGAMAL_reencrypt(bnProdInpA0, bnProdInpB0, a_ths->m_elGroupKey, bnExpList[0]) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdInpA0, bnProdList[0]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdInpB0, bnProdList[1]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (ELGAMAL_reencrypt(bnProdInpA1, bnProdInpB1, a_ths->m_elGroupKey, bnExpList[1]) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdInpA1, bnProdList[2]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdInpB1, bnProdList[3]) != 0) ar_sResult = E_UNKNOWN; // check the products for (UINT32 i = 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { if (ELGAMAL_reencrypt(bnProdList[4*(i - 1)], bnProdList[4*(i - 1) + 1], a_ths->m_elGroupKey, bnExpList[2*i]) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdList[4*(i - 1)], bnProdList[4*i]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdList[4*(i - 1) + 1], bnProdList[4*i + 1]) != 0) ar_sResult = E_UNKNOWN; if (ELGAMAL_reencrypt(bnProdList[4*(i - 1) + 2], bnProdList[4*(i - 1) + 3], a_ths->m_elGroupKey, bnExpList[2*i + 1]) == 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdList[4*(i - 1) + 2], bnProdList[4*i + 2]) != 0) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_cmp(bnProdList[4*(i - 1) + 3], bnProdList[4*i + 3]) != 0) ar_sResult = E_UNKNOWN; } if (bnProdInpA0 != NULL) BN_free(bnProdInpA0); if (bnProdInpB0 != NULL) BN_free(bnProdInpB0); if (bnProdInpA1 != NULL) BN_free(bnProdInpA1); if (bnProdInpB1 != NULL) BN_free(bnProdInpB1); clearBNList(2*MIXCNT, bnExpList, 1); clearBNList(4*MIXCNT, bnProdList, 1); if (ctx != NULL) BN_CTX_free(ctx); return ar_sResult; } SINT32 CAFlashMIX::unblindCheckFirstReEnc(SINT32& ar_sResult, CAFlashMIX* a_ths, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 a_uInpListSize, BIGNUM** a_bnInpList, BIGNUM** a_bnFistList, BIGNUM** a_bnSecondList, UINT32** a_uInpPerm, BIGNUM*** a_bnExp, UINT32 MIXCNT) { if (ar_sResult != E_SUCCESS) return ar_sResult; UINT32 LISTSIZE = a_uInpListSize >> 1; UINT32* uPermList = NULL; BIGNUM** bnExpList = NULL; UINT32 uListSize = 0; BN_CTX* ctx = NULL; BIGNUM** bnPermInp = NULL; UINT32* uPerm0 = NULL; UINT32* uPerm1 = NULL; initCTX(ar_sResult, &ctx); unblindFirstReEncPermData(ar_sResult, &uPermList, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, LISTSIZE, a_uInpPerm, MIXCNT); unblindFirstReEncExpList(ar_sResult, &bnExpList, a_pPrevMIX, a_pNextMIX, a_uSelfIdx, LISTSIZE, a_bnExp, MIXCNT); CAMsg::printMsg(LOG_DEBUG, "check 1 Reenc receive Perm and Exp %s\n", (ar_sResult == E_SUCCESS) ? "successfully finished" : "ERROR"); unblindCalcAkk(ar_sResult, &uPerm0, &uPerm1, LISTSIZE, uPermList, MIXCNT); CAMsg::printMsg(LOG_DEBUG, "check 1 Reenc calc akk perm %s\n", (ar_sResult == E_SUCCESS) ? "successfully finished" : "ERROR"); // calc sum exp of list 0 for (UINT32 i = 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { unblindPermutate(ar_sResult, bnExpList, LISTSIZE, uPermList + 2*(i-1)*LISTSIZE); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) if (BN_mod_add(bnExpList[j], bnExpList[j], bnExpList[(2*i + 0) * LISTSIZE + j], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; } unblindPermutate(ar_sResult, bnExpList, LISTSIZE, uPermList + 2*(MIXCNT-1)*LISTSIZE); for (UINT32 i = 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { unblindPermutate(ar_sResult, bnExpList + LISTSIZE, LISTSIZE, uPermList + (2*(i-1)+1)*LISTSIZE); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) if (BN_mod_add(bnExpList[LISTSIZE + j], bnExpList[LISTSIZE + j], bnExpList[(2*i + 1)*LISTSIZE + j], a_ths->m_elGroupKey->p, ctx) == 0) ar_sResult = E_UNKNOWN; } unblindPermutate(ar_sResult, bnExpList + LISTSIZE, LISTSIZE, uPermList + (2*(MIXCNT-1)+1)*LISTSIZE); copyBNList(ar_sResult, &bnPermInp, a_uInpListSize, a_bnInpList); unblindPermutateMsg(ar_sResult, bnPermInp, a_uInpListSize, uPerm0); if (ar_sResult == E_SUCCESS) if (ELGAMAL_reencrypt(bnPermInp, a_ths->m_elGroupKey, LISTSIZE, bnExpList) == 0) ar_sResult = E_UNKNOWN; // check the values for (UINT32 i = 0; (i < a_uInpListSize) && (ar_sResult == E_SUCCESS); i++) if (BN_cmp(bnPermInp[i], a_bnFistList[i]) != 0) ar_sResult = E_UNKNOWN; clearBNList(a_uInpListSize, bnPermInp); bnPermInp = NULL; copyBNList(ar_sResult, &bnPermInp, a_uInpListSize, a_bnInpList); unblindPermutateMsg(ar_sResult, bnPermInp, a_uInpListSize, uPerm1); if (ar_sResult == E_SUCCESS) if (ELGAMAL_reencrypt(bnPermInp, a_ths->m_elGroupKey, LISTSIZE, bnExpList + LISTSIZE) == 0) ar_sResult = E_UNKNOWN; // check the values for (UINT32 i = 0; (i < a_uInpListSize) && (ar_sResult == E_SUCCESS); i++) if (BN_cmp(bnPermInp[i], a_bnSecondList[i]) != 0) ar_sResult = E_UNKNOWN; clearBNList(2 * MIXCNT * LISTSIZE, bnExpList, 1); clearBNList(a_uInpListSize, bnPermInp); delete[] uPermList; delete[] uPerm0; delete[] uPerm1; clearCTX(&ctx); return ar_sResult; } SINT32 CAFlashMIX::unblindFirstReEncPermData(SINT32& ar_sResult, UINT32** r_uPermList, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 LISTSIZE, UINT32** a_uInpPerm, UINT32 MIXCNT) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((*r_uPermList = new UINT32[2 * MIXCNT * LISTSIZE]) == NULL) ar_sResult = E_UNKNOWN; // receive input permutation of prev mix for (UINT32 i = 0; (i < a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveUINT32((*r_uPermList)[(2*i + 0)*LISTSIZE + j], a_pPrevMIX); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveUINT32((*r_uPermList)[(2*i + 1)*LISTSIZE + j], a_pPrevMIX); } // add own permutation for (UINT32 i = 0; (i < LISTSIZE) && (ar_sResult == E_SUCCESS); i++) { (*r_uPermList)[(2*a_uSelfIdx + 0)*LISTSIZE + i] = a_uInpPerm[0][i]; (*r_uPermList)[(2*a_uSelfIdx + 1)*LISTSIZE + i] = a_uInpPerm[1][i]; } if (a_uSelfIdx < MIXCNT - 1) { // send data to next mix for (UINT32 i = 0; (i <= a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendUINT32(a_pNextMIX, (*r_uPermList)[(2*i + 0)*LISTSIZE + j]); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendUINT32(a_pNextMIX, (*r_uPermList)[(2*i + 1)*LISTSIZE + j]); } // receive data from next mix for (UINT32 i = a_uSelfIdx + 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveUINT32((*r_uPermList)[(2*i + 0)*LISTSIZE + j], a_pNextMIX); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveUINT32((*r_uPermList)[(2*i + 1)*LISTSIZE + j], a_pNextMIX); } } // send to prev mix if (a_uSelfIdx > 0) for (UINT32 i = a_uSelfIdx; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendUINT32(a_pPrevMIX, (*r_uPermList)[(2*i + 0)*LISTSIZE + j]); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendUINT32(a_pPrevMIX, (*r_uPermList)[(2*i + 1)*LISTSIZE + j]); } return ar_sResult; } SINT32 CAFlashMIX::unblindFirstReEncExpList(SINT32& ar_sResult, BIGNUM*** r_bnExpList, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 LISTSIZE, BIGNUM*** a_bnExp, UINT32 MIXCNT) { if (ar_sResult != E_SUCCESS) return ar_sResult; initBNList(ar_sResult, r_bnExpList, 2 * MIXCNT * LISTSIZE); // receive exp from prev mix for (UINT32 i = 0; (i < a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveBN(&((*r_bnExpList)[(2*i + 0)*LISTSIZE + j]), a_pPrevMIX); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveBN(&((*r_bnExpList)[(2*i + 1)*LISTSIZE + j]), a_pPrevMIX); } // add own data to list for (UINT32 i = 0; (i < LISTSIZE) && (ar_sResult == E_SUCCESS); i++) { (*r_bnExpList)[(2*a_uSelfIdx + 0)*LISTSIZE + i] = BN_dup(a_bnExp[0][i]); (*r_bnExpList)[(2*a_uSelfIdx + 1)*LISTSIZE + i] = BN_dup(a_bnExp[1][i]); } if (a_uSelfIdx < MIXCNT - 1) { // send data to next mix for (UINT32 i = 0; (i <= a_uSelfIdx) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendBN(a_pNextMIX, (*r_bnExpList)[(2*i + 0)*LISTSIZE + j]); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendBN(a_pNextMIX, (*r_bnExpList)[(2*i + 1)*LISTSIZE + j]); } // receive data from next mix for (UINT32 i = a_uSelfIdx + 1; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveBN(&((*r_bnExpList)[(2*i + 0)*LISTSIZE + j]), a_pNextMIX); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = receiveBN(&((*r_bnExpList)[(2*i + 1)*LISTSIZE + j]), a_pNextMIX); } } // send data to prev mix if (a_uSelfIdx > 0) for (UINT32 i = a_uSelfIdx; (i < MIXCNT) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendBN(a_pPrevMIX, (*r_bnExpList)[(2*i + 0)*LISTSIZE + j]); for (UINT32 j = 0; (j < LISTSIZE) && (ar_sResult == E_SUCCESS); j++) ar_sResult = sendBN(a_pPrevMIX, (*r_bnExpList)[(2*i + 1)*LISTSIZE + j]); } return ar_sResult; } SINT32 CAFlashMIX::unblindCalcAkkPerm(SINT32& ar_sResult, UINT32** r_uPerm0, UINT32** r_uPerm1, UINT32* a_uPermList, UINT32 MIXCNT, UINT32 LISTSIZE) { if (ar_sResult != E_SUCCESS) return ar_sResult; UINT32 uTmp = 0; if ((*r_uPerm0 = new UINT32[LISTSIZE]) == NULL) ar_sResult = E_UNKNOWN; if ((*r_uPerm1 = new UINT32[LISTSIZE]) == NULL) ar_sResult = E_UNKNOWN; uTmp = a_uPermList[0]; for (UINT32 i = 0; (i < LISTSIZE) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < MIXCNT) && (ar_sResult == E_SUCCESS); j++) getNextPermElement(ar_sResult, uTmp, LISTSIZE, a_uPermList + 2*j*LISTSIZE, uTmp); (*r_uPerm0)[i] = uTmp; } uTmp = a_uPermList[LISTSIZE]; for (UINT32 i = 0; (i < LISTSIZE) && (ar_sResult == E_SUCCESS); i++) { for (UINT32 j = 0; (j < MIXCNT) && (ar_sResult == E_SUCCESS); j++) getNextPermElement(ar_sResult, uTmp, LISTSIZE, a_uPermList + (2*j+1)*LISTSIZE, uTmp); (*r_uPerm1)[i] = uTmp; } return ar_sResult; } SINT32 CAFlashMIX::unblindCalcAkk(SINT32& ar_sResult, UINT32** r_uPerm0, UINT32** r_uPerm1, UINT32 LISTSIZE, UINT32* a_uPermList, UINT32 MIXCNT) { if (ar_sResult != E_SUCCESS) return ar_sResult; UINT32 uTmp = 0; SINT32 i = 0; bool bNew = false; if ((*r_uPerm0 = new UINT32[2*LISTSIZE]) == NULL) ar_sResult = E_UNKNOWN; if ((*r_uPerm1 = new UINT32[2*LISTSIZE]) == NULL) ar_sResult = E_UNKNOWN; for (i = 0; (i < 2*LISTSIZE) && (ar_sResult == E_SUCCESS); i++) { (*r_uPerm0)[i] = 0xFFFFFFFF; (*r_uPerm1)[i] = 0xFFFFFFFF; } i = 0; while (unblindGetFirstL1NotInL2(ar_sResult, uTmp, LISTSIZE, a_uPermList, 2*LISTSIZE, *r_uPerm0) == E_SUCCESS) { bNew = false; while (!bNew) { for (UINT32 j = 0; (j < MIXCNT) && (ar_sResult == E_SUCCESS); j++) getNextPermElement(ar_sResult, uTmp, LISTSIZE, a_uPermList + 2*j*LISTSIZE, uTmp); if (getIdx(2*LISTSIZE, *r_uPerm0, uTmp) < 0) (*r_uPerm0)[i] = uTmp; else bNew = true; i++; } }/**/ i = 0; while (unblindGetFirstL1NotInL2(ar_sResult, uTmp, LISTSIZE, a_uPermList + LISTSIZE, 2*LISTSIZE, *r_uPerm1) == E_SUCCESS) { bNew = false; while (!bNew) { for (UINT32 j = 0; (j < MIXCNT) && (ar_sResult == E_SUCCESS); j++) getNextPermElement(ar_sResult, uTmp, LISTSIZE, a_uPermList + (2*j+1)*LISTSIZE, uTmp); if (getIdx(2*LISTSIZE, *r_uPerm1, uTmp) < 0) (*r_uPerm1)[i] = uTmp; else bNew = true; i++; } }/**/ return ar_sResult; } SINT32 CAFlashMIX::unblindGetFirstL1NotInL2(SINT32& ar_sResult, UINT32& r_uElement, UINT32 a_uList1Size, UINT32* a_uList1, UINT32 a_uList2Size, UINT32* a_uList2) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((a_uList1 == NULL) || (a_uList2 == NULL)) { ar_sResult = E_UNKNOWN; return ar_sResult; } for (UINT32 i = 0; i < a_uList1Size; i++) { bool bIsInList = false; for (UINT32 j = 0; (j < a_uList2Size) && (bIsInList == false); j++) if (a_uList2[j] == a_uList1[i]) bIsInList = true; if (bIsInList == false) { r_uElement = a_uList1[i]; return E_SUCCESS; } } return E_UNKNOWN; } SINT32 CAFlashMIX::unblindPermutate(SINT32& ar_sResult, BIGNUM** ar_bnList, UINT32 a_uListSize, UINT32* a_uPerm) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((ar_bnList == NULL) || (a_uPerm == NULL)) { ar_sResult E_UNKNOWN; return ar_sResult; } for (UINT32 i = 1; i < a_uListSize; i++) { BIGNUM* bnTmp = ar_bnList[a_uPerm[0]]; ar_bnList[a_uPerm[0]] = ar_bnList[a_uPerm[i]]; ar_bnList[a_uPerm[i]] = bnTmp; } return ar_sResult; }/**/ SINT32 CAFlashMIX::unblindPermutateMsg(SINT32& ar_sResult, BIGNUM** ar_bnList, UINT32 a_uListSize, UINT32* a_uPerm) { if (ar_sResult != E_SUCCESS) return ar_sResult; if ((ar_bnList == NULL) || (a_uPerm == NULL)) { ar_sResult=E_UNKNOWN; return ar_sResult; } UINT32 uPL = 0; UINT32 uPH = 0; while (unblindPermSetPtr(uPL, uPH, a_uListSize, a_uPerm) == E_SUCCESS) { switchEncListElements(a_uListSize, ar_bnList, a_uPerm[uPL], a_uPerm[uPH]); } return ar_sResult; } SINT32 CAFlashMIX::unblindPermSetPtr(UINT32& ar_uPtrL, UINT32& ar_uPtrH, UINT32 a_uListSize, UINT32* a_uPerm) { ar_uPtrH++; if (ar_uPtrH >= a_uListSize) return E_UNKNOWN; if (a_uPerm[ar_uPtrH] == 0xFFFFFFFF) { ar_uPtrH++; if (a_uPerm[ar_uPtrH] == 0xFFFFFFFF) return E_UNKNOWN; ar_uPtrL = ar_uPtrH; ar_uPtrH++; if (ar_uPtrH == 0xFFFFFFFF) ar_uPtrH--; } return E_SUCCESS; } SINT32 CAFlashMIX::decrypt(CAFlashMIX* a_ths, CASocket* a_pBB) { if ((a_ths == NULL) || (a_pBB == NULL)) return E_UNKNOWN; CAMsg::printMsg(LOG_DEBUG, "decryption startet\n"); UINT32 MIXCNT = a_ths->m_uMIXDecryptCnt; SINT32 result = E_SUCCESS; UINT32* uDecryptList = NULL; UINT32 uSelfIdx = 0xFFFFFFFF; UINT32 uThsMIXIdx = 0xFFFFFFFF; BIGNUM** bnInpList = NULL; UINT32 uInpListSize = 0; BIGNUM* bnSharedExp = NULL; BIGNUM* bnTmp = NULL; BN_CTX* ctx = NULL; CASocket* pNextMIX = NULL; CASocket* pPrevMIX = NULL; initBN(result, &bnTmp); initCTX(result, &ctx); if ((uDecryptList = new UINT32[MIXCNT]) == NULL) result = E_UNKNOWN; receiveUINT32(result, uSelfIdx, a_pBB); for (UINT32 i = 0; (i < MIXCNT) && (result == E_SUCCESS); i++) result = receiveUINT32(uDecryptList[i], a_pBB); CAMsg::printMsg(LOG_DEBUG, "receive decryption list: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // connect if (result == E_SUCCESS) result = decryptConnectMIX(&pPrevMIX, &pNextMIX, a_ths, uSelfIdx, uDecryptList); CAMsg::printMsg(LOG_DEBUG, "connect to prev and next mix: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // receive inputlist if (uSelfIdx == 0) receiveSignedBNArray(result, uInpListSize, &bnInpList, a_ths->m_elBBSignKey, a_pBB); else receiveSignedBNArray(result, uInpListSize, &bnInpList, a_ths->m_vMIXData[uDecryptList[uSelfIdx - 1]]->elSignKey, pPrevMIX); CAMsg::printMsg(LOG_DEBUG, "receive inputlist: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); // decrypt uThsMIXIdx = getMIXIdx(a_ths->m_pMutexMIXData, a_ths->m_uMIXCnt, a_ths->m_vMIXData, a_ths->m_uLocalIP, a_ths->m_uPort); if (result == E_SUCCESS) if (ELGAMAL_calcSharedExp(&bnSharedExp, a_ths->m_uMIXCnt, MIXCNT, uDecryptList, uThsMIXIdx, a_ths->m_elGroupKey->x, a_ths->m_elGroupKey->q) != ELGAMAL_SUCCESS) result = E_UNKNOWN; for (UINT32 i = 0; (i < uInpListSize) && (result == E_SUCCESS); i += 2) { if (BN_mod_exp(bnTmp, bnInpList[i + 1], bnSharedExp, a_ths->m_elGroupKey->p, ctx) == 0) result = E_UNKNOWN; else if (BN_mod_mul(bnInpList[i], bnInpList[i], bnTmp, a_ths->m_elGroupKey->p, ctx) == 0) result = E_UNKNOWN; } // send the list if (uSelfIdx < MIXCNT - 1) sendSignedBNArray(result, a_ths->m_elSignKey, pNextMIX, uInpListSize, bnInpList); else { // send to receivers for (UINT32 i = 0; (i < uInpListSize) && (result == E_SUCCESS); i += 2) { decryptSendMessage(result, bnInpList[i]); } } CAMsg::printMsg(LOG_DEBUG, "list send to next mix: %s\n", (result == E_SUCCESS) ? "successfully finished" : "ERROR"); if (result == E_SUCCESS) result = sendUINT32(a_pBB, DECRYPT_SUCCESS); else sendUINT32(a_pBB, DECRYPT_ERROR); CAMsg::printMsg(LOG_DEBUG, "decryption finished\n"); if (pPrevMIX != NULL) pPrevMIX->close(); if (pNextMIX != NULL) pNextMIX->close(); delete pPrevMIX; delete pNextMIX; delete[] uDecryptList; clearBN(&bnSharedExp); clearBN(&bnTmp); clearCTX(&ctx); return result; } SINT32 CAFlashMIX::decryptConnectMIX(CASocket** r_pPrevMIX, CASocket** r_pNextMIX, CAFlashMIX* a_ths, UINT32 a_uSelfIdx, UINT32* a_uDecryptList) { if ((r_pPrevMIX == NULL) || (r_pNextMIX == NULL) || (a_ths == NULL)) return E_UNKNOWN; SINT32 result = E_SUCCESS; delete *r_pPrevMIX; *r_pPrevMIX = NULL; delete *r_pNextMIX; *r_pNextMIX = NULL; // connect prev and next mix if (a_uSelfIdx > 0) { if ((*r_pNextMIX = new CASocket()) == NULL) result = E_UNKNOWN; else result = (*r_pNextMIX)->listen(a_ths->m_uPortDecrypt); if ((*r_pPrevMIX = new CASocket()) == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) result = (*r_pNextMIX)->accept(**r_pPrevMIX); if (*r_pNextMIX != NULL) (*r_pNextMIX)->close(); delete *r_pNextMIX; *r_pNextMIX = NULL; } // connect to next mixes if (a_uSelfIdx < a_ths->m_uMIXDecryptCnt - 1) { CASocketAddrINet* pAddr = NULL; initSocket(result, r_pNextMIX); initSocketAddrINet(result, &pAddr); MIXDATA* pMIXData = a_ths->m_vMIXData[a_uDecryptList[a_uSelfIdx + 1]]; if (initSocketAddrINet(result, &pAddr) == E_SUCCESS) result = pAddr->setAddr(pMIXData->cIP, pMIXData->uPortDecrypt); if (result == E_SUCCESS) result = (*r_pNextMIX)->connect(*pAddr, 5000, 1); delete pAddr; } if (result != E_SUCCESS) { delete *r_pPrevMIX; *r_pPrevMIX = NULL; delete *r_pNextMIX; *r_pNextMIX = NULL; } return result; } SINT32 CAFlashMIX::decryptSendMessage(SINT32& ar_sResult, BIGNUM* a_bnMsg) { if (ar_sResult != E_SUCCESS) return ar_sResult; if (a_bnMsg == NULL) { ar_sResult = E_UNKNOWN; return ar_sResult; } CASocket* pSocket = NULL; CASocketAddrINet* pAddr = NULL; UINT8* uBN = NULL; UINT32 uBNSize = 0; initSocket(ar_sResult, &pSocket); initSocketAddrINet(ar_sResult, &pAddr); uBNSize = BN_num_bytes(a_bnMsg); if ((uBN = new UINT8[uBNSize]) == NULL) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) if (BN_bn2bin(a_bnMsg, uBN) != uBNSize) ar_sResult = E_UNKNOWN; if (ar_sResult == E_SUCCESS) ar_sResult = pAddr->setIP(uBN); if (ar_sResult == E_SUCCESS) ar_sResult = pAddr->setPort(((UINT16*)uBN)[2]); if (ar_sResult == E_SUCCESS) ar_sResult = pSocket->connect(*pAddr, 5, 1); sendUINT8Arr(pSocket, uBNSize - 6, uBN + 6); delete[] uBN; if (pSocket != NULL) pSocket->close(); delete pSocket; delete pAddr; return ar_sResult; } anon-proxy-00.05.38+20081230/FlashMix/FlashMixGlobal.hpp0000644000175000017500000001270210162311576021000 0ustar daviddavid#ifndef __FLASH_MIX_GLOBAL__ #define __FLASH_MIX_GLOBAL__ #include "../StdAfx.h" #include "../CAMutex.hpp" #include "../CASocket.hpp" #include "../CASocketAddrINet.hpp" #include "elgamal.hpp" static const UINT32 BB_REQ_USER_DATA = 0x00000000; static const UINT32 BB_REQ_INIT_MIX = 0x00000001; static const UINT32 BB_REQ_REMOVE_MIX = 0x00000002; static const UINT32 BB_REQ_GET_SIGN_KEY = 0x00000003; static const UINT32 BB_REQ_GET_ENC_KEY = 0x00000004; static const UINT32 BB_REQ_GET_GROUP_KEY = 0x00000005; static const UINT32 BB_REQ_UNDEF = 0xFFFFFFFF; static const UINT32 MIX_REQ_KEY_SHARE = 0x00000010; static const UINT32 MIX_REQ_DUMMY = 0x00000011; static const UINT32 MIX_REQ_BLIND = 0x00000012; static const UINT32 MIX_REQ_MIX_PROCESS = 0x00000013; static const UINT32 MIX_REQ_DECRYPT = 0x00000014; static const UINT32 MIX_REQ_UNDEF = 0xFFFFFFFF; static const UINT32 PROCESS_SUCCESS = 0x00000020; static const UINT32 PROCESS_FINISH = 0x00000021; static const UINT32 PROCESS_ERROR = 0x00000022; static const UINT32 PROCESS_UNDEF = 0xFFFFFFFF; static const UINT32 BLIND_SUCCESS = 0x00000030; static const UINT32 BLIND_ERROR = 0x00000031; static const UINT32 BLIND_UNDEF = 0xFFFFFFFF; static const UINT32 UNBLIND_SUCCESS = 0x00000040; static const UINT32 UNBLIND_ERROR = 0x00000041; static const UINT32 UNBLIND_UNDEF = 0xFFFFFFFF; static const UINT32 USERDATA_SUCCESS = 0x00000050; static const UINT32 USERDATA_ERROR = 0x00000051; static const UINT32 USERDATA_UNDEF = 0xFFFFFFFF; static const UINT32 DECRYPT_SUCCESS = 0x00000060; static const UINT32 DECRYPT_ERROR = 0x00000061; static const UINT32 DECRYPT_UNDEF = 0xFFFFFFFF; typedef struct stMIXData MIXDATA; struct stMIXData { UINT8* cIP; UINT32 uMainPort; UINT32 uPortKeyShare; UINT32 uPortDummy; UINT32 uPortBlind; UINT32 uPortDecrypt; ELGAMAL* elEncKey; ELGAMAL* elSignKey; }; MIXDATA* MIXDATA_new(); void MIXDATA_free(MIXDATA* a_pMIXData); // initialize a BIGNUM SINT32 initBN(BIGNUM** r_bn, UINT32 a_uSetWord = 0); SINT32 initBN(SINT32& ar_sResult, BIGNUM** r_bn, UINT32 a_uSetWord = 0); void clearBN(BIGNUM** a_bn); SINT32 initBNRand(BIGNUM** r_bn, UINT32 a_uBitLength); SINT32 initBNRand(SINT32& ar_sResult, BIGNUM** r_bn, UINT32 a_uBitLength); SINT32 initCTX(BN_CTX** r_ctx); SINT32 initCTX(SINT32& ar_sResult, BN_CTX** r_ctx); void clearCTX(BN_CTX** a_ctx); // allocates memory for the list and init all values with NULL SINT32 initBNList(BIGNUM*** r_bnList, UINT32 a_bnListSize); SINT32 initBNList(SINT32& ar_sResult, BIGNUM*** r_bnList, UINT32 a_bnListSize); // frees the complete list of bignum SINT32 clearBNList(UINT32 a_uListSize, BIGNUM** a_bnList, UINT8 a_uFreeArray = 0); SINT32 clearBNList(SINT32& ar_sResult, UINT32 a_uListSize, BIGNUM** a_bnList, UINT8 a_uFreeArray = 0); // create a copy of a bignum list SINT32 copyBNList(BIGNUM*** a_bnCopy, UINT32 a_uListSize, BIGNUM** a_bnSource); SINT32 copyBNList(SINT32& ar_sResult, BIGNUM*** a_bnCopy, UINT32 a_uListSize, BIGNUM** a_bnSource); // returns the first free index to this list // returns -1 if the list is full or error SINT32 getFreeIdx(UINT32 a_uListSize, void** a_vList); SINT32 insertToList(UINT32 a_uListSize, void** a_vList, void* a_vListElement); SINT32 insertToList(CAMutex* a_pMutex, UINT32 a_uListSize, void** a_vList, void* a_vListElement); SINT32 insertToMIXList(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData, MIXDATA* a_pMIXData); SINT32 deleteFromMIXList(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData, UINT32 a_uIdx); UINT32 getMIXIdx(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData, UINT8* a_uIP, UINT32 a_uMainPort); SINT32 clearMIXList(CAMutex* a_pMIXMutex, UINT32 a_uMIXCnt, MIXDATA** a_vMIXData); SINT32 initMIXList(MIXDATA*** a_vMIXData, UINT32 a_uMIXCnt); SINT32 initMIXList(SINT32& ar_sResult, MIXDATA*** a_vMIXData, UINT32 a_uMIXCnt); SINT32 getNextPermElement(SINT32& ar_sResult, UINT32& r_uIdx, UINT32 a_uListSize, UINT32* a_uPermList, UINT32 a_uPrevElement); // returns the index of a_uValue in the list and -1 of it isnt in the list SINT32 getIdx(UINT32 a_uListSize, UINT32* a_uList, UINT32 a_uValue); SINT32 createRndList(UINT32** r_uList, UINT32 a_uListSize, UINT32 a_uModul); SINT32 createRndList(SINT32& ar_sResult, UINT32** r_uList, UINT32 a_uListSize, UINT32 a_uModul); SINT32 initSocket(CASocket** r_pSocket); SINT32 initSocket(SINT32& ar_sResult, CASocket** r_pSocket); SINT32 initSocketAddrINet(CASocketAddrINet** r_pAddr); SINT32 initSocketAddrINet(SINT32& ar_sResult, CASocketAddrINet** r_pAddr); SINT32 initAddrSocket(CASocket** r_pSocket, CASocketAddrINet** r_pAddr, UINT8* a_uIP, UINT16 a_uPort, UINT8 a_uConnect = 0); SINT32 initAddrSocket(SINT32& ar_sResult, CASocket** r_pSocket, CASocketAddrINet** r_pAddr, UINT8* a_uIP, UINT16 a_uPort, UINT8 a_uConnect = 0); SINT32 initSocketList(CASocket*** r_pSockets, UINT32 a_uListSize); SINT32 initSocketList(SINT32& ar_sResult, CASocket*** r_pSockets, UINT32 a_uListSize); SINT32 clearSocketList(UINT32 a_uListSize, CASocket** a_pSockets); SINT32 initSocketAddrINetList(CASocketAddrINet*** r_pAddrs, UINT32 a_uListSize); SINT32 initSocketAddrINetList(SINT32& ar_sResult, CASocketAddrINet*** r_pAddrs, UINT32 a_uListSize); SINT32 clearSocketAddrINetList(UINT32 a_uListSize, CASocketAddrINet** a_pAddrs); #endif anon-proxy-00.05.38+20081230/FlashMix/Array.cpp0000644000175000017500000000005410162311576017212 0ustar daviddavid#include "../StdAfx.h" #include "Array.hpp" anon-proxy-00.05.38+20081230/FlashMix/FlashMixUser.vcproj0000644000175000017500000002474310763776144021257 0ustar daviddavid anon-proxy-00.05.38+20081230/FlashMix/FlashMixUser.cpp0000644000175000017500000001525710676452766020542 0ustar daviddavid#include "../StdAfx.h" #include "../CACmdLnOptions.hpp" #include "../CAMsg.hpp" #include "elgamal.hpp" #include "CABNSend.hpp" #include "FlashMixGlobal.hpp" #include #ifdef __BORLANDC__ #pragma argsused #endif CACmdLnOptions* pglobalOptions; void log(int line, SINT32 result, char* des, int msg) { std::cout << "Line: " << line << " Result: " << result << " " << des << " " << msg << std::endl; } void coutbn(BIGNUM* bn) { char* c = BN_bn2hex(bn); CAMsg::printMsg(LOG_DEBUG, "BN: %s\n", c); OPENSSL_free(c); } unsigned int port = 65000; unsigned int msg = 1024; unsigned int bbPort = 16000; UINT8* bbIP = NULL; UINT8* localIP = NULL; UINT8 localIPArr[4]; void readParam(int argc, char* argv[]) { for (int i = 0; i < argc; i++) { if (strstr(argv[i], "--port=") == argv[i]) port = atoi(argv[i] + 7); else if (strstr(argv[i], "--bbPort=") == argv[i]) bbPort = atoi(argv[i] + 9); else if (strstr(argv[i], "--msg=") == argv[i]) msg = atoi(argv[i] + 6); else if (strstr(argv[i], "--bbIP=") == argv[i]) { free((char*)bbIP); bbIP = (UINT8*)strdup(argv[i] + 7); } else if (strstr(argv[i], "--localIP=") == argv[i]) { free((char*)localIP); localIP = (UINT8*)strdup(argv[i] + 10); } else if (strstr(argv[i], "/port=") == argv[i]) port = atoi(argv[i] + 6); else if (strstr(argv[i], "/bbPort=") == argv[i]) bbPort = atoi(argv[i] + 8); else if (strstr(argv[i], "/msg=") == argv[i]) msg = atoi(argv[i] + 5); else if (strstr(argv[i], "/bbIP=") == argv[i]) { free((char*)bbIP); bbIP = (UINT8*)strdup(argv[i] + 6); } else if (strstr(argv[i], "/localIP=") == argv[i]) { free((char*)localIP); localIP = (UINT8*)strdup(argv[i] + 9); } } } void fillIPArr(UINT8 r_ipArr[4], UINT8* a_cIP) { UINT32 cIPPtrL = 0; UINT32 cIPPtrH = 0; for (UINT32 i = 0; i < 4; i++) { // find '.' if (i < 3) { for ( ; a_cIP[cIPPtrH] != '.'; cIPPtrH++) ; a_cIP[cIPPtrH] = 0; r_ipArr[i] = atoi((char*)(a_cIP + cIPPtrL)); a_cIP[cIPPtrH] = '.'; cIPPtrH++; cIPPtrL = cIPPtrH; } else r_ipArr[i] = atoi((char*)(a_cIP + cIPPtrL)); } } int main( int argc, char * argv[] ) { #ifdef _WIN32 int err = 0; WSADATA wsadata; err = WSAStartup(0x0202, &wsadata); #endif CASocketAddrINet::init(); CAMsg::init(); bbIP = (UINT8*)strdup("127.0.0.1"); localIP = (UINT8*)strdup("127.0.0.1"); readParam(argc, argv); fillIPArr(localIPArr, localIP); SINT32 result = E_SUCCESS; CASocketAddrINet* pAddr = NULL; CASocket* pSocket = NULL; pSocket->create(); ELGAMAL* elBBSignKey = NULL; ELGAMAL* elGroupKey = NULL; UINT32 cnt = 0; UINT64 tStart = 0, tEndFirst = 0, tEndLast = 0; // connect to BB initSocket(result, &pSocket); initSocketAddrINet(result, &pAddr); if (result == E_SUCCESS) result = pAddr->setAddr(bbIP, bbPort); if (result == E_SUCCESS) result = pSocket->connect(*pAddr, 50, 1); sendUINT32(result, pSocket, BB_REQ_GET_SIGN_KEY); receivePublicKey(result, &elBBSignKey, pSocket); if (pSocket != NULL) pSocket->close(); if (result == E_SUCCESS) result = pSocket->connect(*pAddr, 50, 1); sendUINT32(result, pSocket, BB_REQ_GET_GROUP_KEY); receiveSignedPublicKey(result, &elGroupKey, elBBSignKey, pSocket); if (pSocket != NULL) pSocket->close(); delete pSocket; pSocket = NULL; for (UINT32 i = 0; (i < msg) && (result == E_SUCCESS); i++) { BIGNUM* bnMsg = NULL; BIGNUM* bnEncA = NULL; BIGNUM* bnEncB = NULL; UINT32 uDataRes = USERDATA_UNDEF; UINT8* uBN = NULL; UINT32 uBNSize = 0; initBNRand(result, &bnMsg, 64); uBNSize = BN_num_bytes(bnMsg); if ((uBN = new UINT8[uBNSize]) == NULL) result = E_UNKNOWN; else if (BN_bn2bin(bnMsg, (unsigned char*)uBN) != uBNSize) result = E_UNKNOWN; for (UINT32 j = 0; (j < 4) && (result == E_SUCCESS); j++) uBN[j] = localIPArr[j]; ((UINT16*)uBN)[2] = port; if (result == E_SUCCESS) if (BN_bin2bn((unsigned char*)uBN, uBNSize, bnMsg) == NULL) result = E_UNKNOWN; // coutbn(bnMsg); if (result == E_SUCCESS) if (ELGAMAL_encrypt(&bnEncA, &bnEncB, elGroupKey, bnMsg) == 0) result = E_UNKNOWN; if (initSocket(result, &pSocket) == E_SUCCESS) result = pSocket->connect(*pAddr, 50, 1); sendUINT32(result, pSocket, BB_REQ_USER_DATA); sendBN(result, pSocket, bnEncA); sendBN(result, pSocket, bnEncB); receiveUINT32(result, uDataRes, pSocket); if (i == msg - 1) getcurrentTimeMillis(tStart); if (uDataRes != USERDATA_SUCCESS) result = E_UNKNOWN; if (pSocket != NULL) pSocket->close(); delete pSocket; pSocket = NULL; delete[] uBN; if (bnMsg != NULL) BN_free(bnMsg); if (bnEncA != NULL) BN_free(bnEncA); if (bnEncB != NULL) BN_free(bnEncB); } CAMsg::printMsg(LOG_DEBUG, "messages send: %s\n", (result == E_SUCCESS) ? "successfull" : "ERROR"); if (pSocket != NULL) pSocket->close(); delete pSocket; pSocket = NULL; if (initSocket(result, &pSocket) == E_SUCCESS) result = pSocket->listen(port); for (UINT32 i = 0; (i < msg) && (result == E_SUCCESS); i++) { BIGNUM* bn = NULL; CASocket* pClient = new CASocket(); UINT8* cBN = NULL; if (pClient == NULL) result = E_UNKNOWN; if (result == E_SUCCESS) result = pSocket->accept(*pClient); if (receiveBN(result, &bn, pClient) == E_SUCCESS) { if (i == 0) getcurrentTimeMillis(tEndFirst); if (i == msg - 1) getcurrentTimeMillis(tEndLast); // coutbn(bn); } if (bn != NULL) BN_free(bn); if (pClient != NULL) pClient->close(); delete pClient; } CAMsg::printMsg(LOG_DEBUG, "first message received after %u milliseconds\n", diff64(tEndFirst, tStart)); CAMsg::printMsg(LOG_DEBUG, "last message received after %u milliseconds\n", diff64(tEndLast , tStart)); ELGAMAL_free(elGroupKey); ELGAMAL_free(elBBSignKey); if (pSocket != NULL) pSocket->close(); delete pSocket; delete pAddr; return result; } anon-proxy-00.05.38+20081230/FlashMix/elgamal.cpp0000644000175000017500000006033310162311576017544 0ustar daviddavid#include "../StdAfx.h" #include "elgamal.hpp" int getListIdx(unsigned int a_uListSize, unsigned int* a_uList, unsigned int a_uValue) { if (a_uList == NULL) return -1; for (unsigned int i = 0; i < a_uListSize; i++) if (a_uList[i] == a_uValue) return i; return -1; } int BNInit(int& ar_sResult, BIGNUM** r_bn, unsigned int a_uSetWord = 0) { if (ar_sResult != ELGAMAL_SUCCESS) return ar_sResult; if (r_bn == NULL) { ar_sResult = ELGAMAL_ERROR; return ar_sResult; } if (*r_bn != NULL) { ar_sResult = ELGAMAL_ERROR; return ar_sResult; } if ((*r_bn = BN_new()) == NULL) ar_sResult = ELGAMAL_ERROR; else BN_init(*r_bn); if (ar_sResult == ELGAMAL_SUCCESS) if (BN_set_word(*r_bn, a_uSetWord) != 1) ar_sResult = ELGAMAL_ERROR; if (ar_sResult != ELGAMAL_SUCCESS) { if (*r_bn != NULL) BN_free(*r_bn); *r_bn = NULL; } return ar_sResult; } int CTXInit(int& ar_sResult, BN_CTX** r_ctx) { if (ar_sResult != ELGAMAL_SUCCESS) return ar_sResult; if (r_ctx == NULL) { ar_sResult = ELGAMAL_ERROR; return ar_sResult; } if (*r_ctx != NULL) { ar_sResult = ELGAMAL_ERROR; return ar_sResult; } if ((*r_ctx = BN_CTX_new()) == NULL) ar_sResult = ELGAMAL_ERROR; else BN_CTX_init(*r_ctx); return ar_sResult; } int BNListInit(int& ar_sResult, BIGNUM*** r_bnList, unsigned int a_uSize) { if (ar_sResult != ELGAMAL_SUCCESS) return ar_sResult; if (r_bnList == NULL) { ar_sResult = ELGAMAL_ERROR; return ar_sResult; } if (*r_bnList != NULL) { ar_sResult = ELGAMAL_ERROR; return ar_sResult; } if ((*r_bnList = new BIGNUM*[a_uSize]) == NULL) ar_sResult = ELGAMAL_ERROR; else for (unsigned int i = 0; i < a_uSize; i++) (*r_bnList)[i] = NULL; return ar_sResult; } void BNFree(BIGNUM** a_bn) { if (*a_bn != NULL) BN_free(*a_bn); *a_bn = NULL; } void CTXFree(BN_CTX** a_ctx) { if (*a_ctx != NULL) BN_CTX_free(*a_ctx); *a_ctx = NULL; } void BNClearFree(BIGNUM** a_bn) { if (*a_bn != NULL) BN_clear_free(*a_bn); *a_bn = NULL; } void BNListFree(unsigned int a_uSize, BIGNUM*** a_bnList, unsigned int a_uFreeArray = 1) { if (a_bnList == NULL) return; for (unsigned int i = 0; i < a_uSize; i++) BNClearFree(&((*a_bnList)[i])); if (a_uFreeArray == 1) { delete[] *a_bnList; *a_bnList = NULL; } } ELGAMAL* ELGAMAL_new(void) { ELGAMAL* ret; int result = ELGAMAL_SUCCESS; if ((ret = (ELGAMAL*)OPENSSL_malloc(sizeof(ELGAMAL))) == NULL) result = ELGAMAL_ERROR; else { ret->p = NULL; ret->pm1 = NULL; ret->q = NULL; ret->g = NULL; ret->x = NULL; ret->y = NULL; } BNInit(result, &(ret->p)); BNInit(result, &(ret->pm1)); BNInit(result, &(ret->q)); BNInit(result, &(ret->g)); BNInit(result, &(ret->x)); BNInit(result, &(ret->y)); if (result != ELGAMAL_SUCCESS) { BNFree(&(ret->p)); BNFree(&(ret->pm1)); BNFree(&(ret->q)); BNFree(&(ret->g)); BNFree(&(ret->x)); BNFree(&(ret->y)); OPENSSL_free(ret); ret = NULL; } return ret; } void ELGAMAL_free(ELGAMAL* r) { if (r == NULL) return; BNClearFree(&(r->p)); BNClearFree(&(r->pm1)); BNClearFree(&(r->q)); BNClearFree(&(r->g)); BNClearFree(&(r->x)); BNClearFree(&(r->y)); OPENSSL_free(r); } ELGAMAL* ELGAMAL_generate_key(int a_iBits) { int result = ELGAMAL_SUCCESS; ELGAMAL* ret = NULL; BIGNUM* bnTmp = NULL; BN_CTX* ctx = NULL; if ((ret = ELGAMAL_new()) == NULL) result = ELGAMAL_ERROR; CTXInit(result, &ctx); BNInit(result, &bnTmp); // find p if (result == ELGAMAL_SUCCESS) if (BN_generate_prime(ret->p, a_iBits, 1, NULL, NULL, NULL, NULL) == NULL) result = ELGAMAL_ERROR; // calc p - 1 if (result == ELGAMAL_SUCCESS) if (BN_copy(ret->pm1, ret->p) == NULL) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_clear_bit(ret->pm1, 0) == 0) result = ELGAMAL_ERROR; // calc q = (p - 1) / 2 if (result == ELGAMAL_SUCCESS) if (BN_rshift(ret->q, ret->pm1, 1) == 0) result = ELGAMAL_ERROR; // find generator g of Gp if (result == ELGAMAL_SUCCESS) if (BN_zero(bnTmp) == 0) result = ELGAMAL_ERROR; while ((!BN_is_one(bnTmp)) && (result == ELGAMAL_SUCCESS)) { if (BN_rand(ret->g, a_iBits, -1, 0) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_is_one(ret->g)) continue; if (result == ELGAMAL_SUCCESS) if (BN_cmp(ret->g, ret->q) >= 0) continue; if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(bnTmp, ret->g, ret->q, ret->p, ctx) == 0) result = ELGAMAL_ERROR; } if (result == ELGAMAL_SUCCESS) { do { if (BN_rand(ret->x, a_iBits - 1, 0, 0) == 0) result = ELGAMAL_ERROR; } while ((BN_is_one(ret->x)) && (result == ELGAMAL_SUCCESS)); } if (result == ELGAMAL_SUCCESS) result = BN_mod_exp(ret->y, ret->g, ret->x, ret->p, ctx); BNClearFree(&bnTmp); CTXFree(&ctx); if (result != ELGAMAL_SUCCESS) { ELGAMAL_free(ret); ret = NULL; } return ret; } int ELGAMAL_isValidPublicKey(ELGAMAL* a_elKey) { if (a_elKey == NULL) return ELGAMAL_ERROR; if ((a_elKey->p == NULL) || (a_elKey->q == NULL) || (a_elKey->g == NULL) || (a_elKey->y == NULL) || (a_elKey->pm1 == NULL)) return ELGAMAL_ERROR; return ELGAMAL_SUCCESS; } int ELGAMAL_isValidPrivateKey(ELGAMAL* a_elKey) { if (a_elKey == NULL) return ELGAMAL_ERROR; if ((a_elKey->p == NULL) || (a_elKey->q == NULL) || (a_elKey->g == NULL) || (a_elKey->x == NULL) || (a_elKey->pm1 == NULL)) return ELGAMAL_ERROR; return ELGAMAL_SUCCESS; } int ELGAMAL_encrypt(BIGNUM** r_bnEncA, BIGNUM** r_bnEncB, ELGAMAL* a_elKey, BIGNUM* a_bnAlpha, BIGNUM* a_bnMsg) { if ((ELGAMAL_isValidPublicKey(a_elKey) == 0) || (a_bnAlpha == NULL) || (a_bnMsg == NULL)) return ELGAMAL_ERROR; BN_CTX* ctx = NULL; BIGNUM* tmp = NULL; int result = ELGAMAL_SUCCESS; // init BNFree(r_bnEncA); BNFree(r_bnEncB); BNInit(result, r_bnEncA); BNInit(result, r_bnEncB); CTXInit(result, &ctx); BNInit(result, &tmp); // calc a = m*y^alpha mod p if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(tmp, a_elKey->y, a_bnAlpha, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(*r_bnEncA, a_bnMsg, tmp, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; // calc b = g^alpha mod p if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(*r_bnEncB, a_elKey->g, a_bnAlpha, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result != ELGAMAL_SUCCESS) { BNFree(r_bnEncA); BNFree(r_bnEncB); } BNFree(&tmp); CTXFree(&ctx); return result; } int ELGAMAL_encrypt(BIGNUM** r_bnEncA, BIGNUM** r_bnEncB, ELGAMAL* a_elKey, BIGNUM* a_bnMsg) { if ((ELGAMAL_isValidPublicKey(a_elKey) == 0) || (a_bnMsg == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BIGNUM* bnAlpha = NULL; if (BNInit(result, &bnAlpha) == ELGAMAL_SUCCESS) if (BN_rand(bnAlpha, BN_num_bits(a_elKey->q) - 1, 1, 1) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) result = ELGAMAL_encrypt(r_bnEncA, r_bnEncB, a_elKey, bnAlpha, a_bnMsg); BNClearFree(&bnAlpha); return result; } int ELGAMAL_reencrypt(BIGNUM* r_bnEncA, BIGNUM* r_bnEncB, ELGAMAL* a_elKey, BIGNUM* a_bnAlpha) { if ((r_bnEncA == NULL) || (r_bnEncB == NULL) || (a_bnAlpha == NULL) || (ELGAMAL_isValidPublicKey(a_elKey) == 0)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BIGNUM* bnYAl = NULL; BIGNUM* bnGAl = NULL; BN_CTX* ctx = NULL; BNInit(result, &bnYAl); BNInit(result, &bnGAl); CTXInit(result, &ctx); if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(bnYAl, a_elKey->y, a_bnAlpha, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(bnGAl, a_elKey->g, a_bnAlpha, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(r_bnEncA, r_bnEncA, bnYAl, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(r_bnEncB, r_bnEncB, bnGAl, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; CTXFree(&ctx); BNFree(&bnYAl); BNFree(&bnGAl); return result; } int ELGAMAL_reencrypt(BIGNUM** ar_bnList, ELGAMAL* a_elKey, unsigned int a_uListSize, BIGNUM** a_bnAlphaList) { if ((ar_bnList == NULL) || (ELGAMAL_isValidPublicKey(a_elKey) == 0) || (a_bnAlphaList == NULL)) return ELGAMAL_SUCCESS; int result = ELGAMAL_SUCCESS; for (unsigned int i = 0; (i < a_uListSize) && (result == 1); i++) result = ELGAMAL_reencrypt(ar_bnList[2 * i], ar_bnList[2 * i + 1], a_elKey, a_bnAlphaList[i]); return result; } int ELGAMAL_gen_exp(BIGNUM*** r_bnExp, ELGAMAL* a_elPublicKey, unsigned int a_uCount) { if ((r_bnExp == NULL) || (ELGAMAL_isValidPublicKey(a_elPublicKey) == 0)) return ELGAMAL_ERROR; if (*r_bnExp != NULL) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; int sSize = BN_num_bits(a_elPublicKey->q) - 1; BNListInit(result, r_bnExp, a_uCount); for (unsigned int i = 0; (i < a_uCount) && (result == ELGAMAL_SUCCESS); i++) { BNInit(result, &((*r_bnExp)[i])); if (result == ELGAMAL_SUCCESS) if (BN_rand((*r_bnExp)[i], sSize, 1, 1) == 0) result = ELGAMAL_ERROR; } if (result == 0) BNListFree(a_uCount, r_bnExp); return result; } int ELGAMAL_decrypt(BIGNUM** r_bnMsg, ELGAMAL* a_elKey, BIGNUM* a_bnEncA, BIGNUM* a_bnEncB) { if ((ELGAMAL_isValidPrivateKey(a_elKey) == 0) || (a_bnEncA == NULL) || (a_bnEncB == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BN_CTX* ctx = NULL; BIGNUM* tmp = NULL; BNClearFree(r_bnMsg); BNInit(result, r_bnMsg); BNInit(result, &tmp); CTXInit(result, &ctx); if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(tmp, a_bnEncB, a_elKey->x, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_inverse(tmp, tmp, a_elKey->p, ctx) == NULL) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(*r_bnMsg, a_bnEncA, tmp, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result != ELGAMAL_SUCCESS) BNClearFree(r_bnMsg); BNClearFree(&tmp); CTXFree(&ctx); return result; } int ELGAMAL_sign(BIGNUM** r_bnSignS, BIGNUM** r_bnSignK, ELGAMAL* a_elKey, BIGNUM* a_bnAlpha, BIGNUM* a_bnMsg) { if ((ELGAMAL_isValidPrivateKey(a_elKey) == 0) || (a_bnAlpha == NULL) || (a_bnMsg == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BIGNUM* tmp1 = NULL; BIGNUM* tmp2 = NULL; BN_CTX* ctx = NULL; BNFree(r_bnSignS); BNFree(r_bnSignK); BNInit(result, r_bnSignS); BNInit(result, r_bnSignK); BNInit(result, &tmp1); BNInit(result, &tmp2); CTXInit(result, &ctx); // k = g^alpha mod p if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(*r_bnSignK, a_elKey->g, a_bnAlpha, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; // s = (m - x*k)*alpha^-1 mod p-1 if (result == ELGAMAL_SUCCESS) if (BN_mod_inverse(tmp2, a_bnAlpha, a_elKey->pm1, ctx) == NULL) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mul(tmp1, a_elKey->x, *r_bnSignK, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_sub(tmp1, a_bnMsg, tmp1) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(*r_bnSignS, tmp1, tmp2, a_elKey->pm1, ctx) == 0) result = ELGAMAL_ERROR; if (result != ELGAMAL_SUCCESS) { BNFree(r_bnSignS); BNFree(r_bnSignK); } BNFree(&tmp2); BNFree(&tmp1); CTXFree(&ctx); return result; } int ELGAMAL_sign(BIGNUM** r_bnSignS, BIGNUM** r_bnSignK, ELGAMAL* a_elKey, BIGNUM* a_bnMsg) { if ((r_bnSignS == NULL) || (r_bnSignK == NULL) || (ELGAMAL_isValidPrivateKey(a_elKey) == 0) || (a_bnMsg == NULL)) return ELGAMAL_ERROR; int result = 1; BIGNUM* alpha = NULL; BIGNUM* tmp = NULL; BIGNUM* tmp2 = NULL; BN_CTX* ctx = NULL; int bitCnt = 0; bool isInvertable = false; BNInit(result, &alpha); BNInit(result, &tmp, 0); BNInit(result, &tmp2, 0); CTXInit(result, &ctx); bitCnt = BN_num_bits(a_elKey->p); isInvertable = false; while ((result == ELGAMAL_SUCCESS) && ((BN_is_zero(tmp) == 1) || (isInvertable == false))) { if (BN_rand(alpha, bitCnt, -1, 0) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_nnmod(tmp, a_elKey->pm1, alpha, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) { if (BN_mod_inverse(tmp2, alpha, a_elKey->pm1, ctx) == NULL) isInvertable = false; else isInvertable = true; } } if (result == ELGAMAL_SUCCESS) result = ELGAMAL_sign(r_bnSignS, r_bnSignK, a_elKey, alpha, a_bnMsg); if (result != ELGAMAL_SUCCESS) { BNFree(r_bnSignS); BNFree(r_bnSignK); } BNClearFree(&alpha); BNClearFree(&tmp2); BNClearFree(&tmp); CTXFree(&ctx); return result; } int ELGAMAL_test_signature(ELGAMAL* a_elKey, BIGNUM* a_bnMsg, BIGNUM* a_bnSignS, BIGNUM* a_bnSignK) { if ((ELGAMAL_isValidPublicKey(a_elKey) == ELGAMAL_ERROR) || (a_bnMsg == NULL) || (a_bnSignS == NULL) || (a_bnSignK == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BIGNUM* gm = NULL; BIGNUM* yk = NULL; BIGNUM* ks = NULL; BN_CTX* ctx = NULL; BNInit(result, &gm); BNInit(result, &yk); BNInit(result, &ks); CTXInit(result, &ctx); if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(gm, a_elKey->g, a_bnMsg, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(yk, a_elKey->y, a_bnSignK, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(ks, a_bnSignK, a_bnSignS, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(yk, yk, ks, a_elKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_cmp(gm, yk) != 0) result = ELGAMAL_ERROR; BNFree(&gm); BNFree(&yk); BNFree(&ks); CTXFree(&ctx); return result; } int ELGAMAL_choose_polynom(BIGNUM*** r_bnPolynom, unsigned int a_uDegree, ELGAMAL* a_elPublicSharedKey, BIGNUM* a_bnLocalSecret) { if ((*r_bnPolynom != NULL) || (ELGAMAL_isValidPublicKey(a_elPublicSharedKey) == 0) || (a_bnLocalSecret == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BN_CTX* ctx = NULL; BNListInit(result, r_bnPolynom, a_uDegree + 1); CTXInit(result, &ctx); if (result == ELGAMAL_SUCCESS) if (((*r_bnPolynom)[0] = BN_dup(a_bnLocalSecret)) == NULL) result = ELGAMAL_ERROR; for (unsigned int i = 1; (i <= a_uDegree) && (result == ELGAMAL_SUCCESS); i++) { if (BNInit(result, &((*r_bnPolynom)[i])) == ELGAMAL_SUCCESS) if (BN_rand((*r_bnPolynom)[i], BN_num_bits(a_elPublicSharedKey->q), 0, 0) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_nnmod((*r_bnPolynom)[i], (*r_bnPolynom)[i], a_elPublicSharedKey->q, ctx) == 0) result = ELGAMAL_ERROR; } if (result != ELGAMAL_SUCCESS) BNListFree(a_uDegree + 1, r_bnPolynom, 1); CTXFree(&ctx); return result; } int ELGAMAL_calcF(BIGNUM*** r_bnF, ELGAMAL* a_elSharedGroupKey, unsigned int a_ufSize, BIGNUM** a_bnf) { if ((*r_bnF != NULL) || (a_bnf == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BN_CTX* ctx = NULL; BNListInit(result, r_bnF, a_ufSize); CTXInit(result, &ctx); for (unsigned int i = 0; (i < a_ufSize) && (result == ELGAMAL_SUCCESS); i++) { if (BNInit(result, &((*r_bnF)[i])) == ELGAMAL_SUCCESS) if (BN_mod_exp((*r_bnF)[i], a_elSharedGroupKey->g, a_bnf[i], a_elSharedGroupKey->p, ctx) == 0) result = ELGAMAL_ERROR; } if (result != ELGAMAL_SUCCESS) BNListFree(a_ufSize, r_bnF); CTXFree(&ctx); return result; } int ELGAMAL_calc_fij(BIGNUM** r_bn, BIGNUM* a_bnModulo, BIGNUM* a_bnJ, unsigned int a_ufSize, BIGNUM** a_bnf) { if ((r_bn == NULL) || (a_bnModulo == NULL) || (a_bnJ == NULL) || (a_bnf == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BN_CTX* ctx = NULL; BIGNUM* exp = NULL; BNClearFree(r_bn); BNInit(result, r_bn, 0); BNInit(result, &exp, 0); CTXInit(result, &ctx); for (unsigned int i = 0; (i < a_ufSize) && (result == ELGAMAL_SUCCESS); i++) { if (BN_set_word(exp, i) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(exp, a_bnJ, exp, a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(exp, exp, a_bnf[i], a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_add(*r_bn, *r_bn, exp, a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; } if (result != ELGAMAL_SUCCESS) BNFree(r_bn); BNFree(&exp); CTXFree(&ctx); return result; } int ELGAMAL_calc_allfij(BIGNUM*** r_bnfij, BIGNUM* a_bnModulo, unsigned int a_uMIXCnt, unsigned int a_ufSize, BIGNUM** a_bnf) { if ((*r_bnfij != NULL) || (a_bnModulo == NULL) || (a_bnf == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BIGNUM* bnJ = NULL; BNInit(result, &bnJ); BNListInit(result, r_bnfij, a_uMIXCnt); for (unsigned int i = 0; (i < a_uMIXCnt) && (result == ELGAMAL_SUCCESS); i++) { if (BN_set_word(bnJ, i + 1) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) result = ELGAMAL_calc_fij(&(*r_bnfij)[i], a_bnModulo, bnJ, a_ufSize, a_bnf); } if (result != ELGAMAL_SUCCESS) BNListFree(a_uMIXCnt, r_bnfij, 1); BNFree(&bnJ); return result; } int ELGAMAL_calcSi(BIGNUM** r_bn, BIGNUM* a_bnModulo, unsigned int a_uSjiSize, BIGNUM** a_bnSi) { if ((a_bnSi == NULL) || (r_bn == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BN_CTX* ctx = NULL; BNClearFree(r_bn); BNInit(result, r_bn, 0); CTXInit(result, &ctx); for (unsigned int i = 0; (i < a_uSjiSize) && (result == ELGAMAL_SUCCESS); i++) { if (a_bnSi[i] == NULL) { result = ELGAMAL_ERROR; break; } if (BN_mod_add(*r_bn, *r_bn, a_bnSi[i], a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; } if (result != ELGAMAL_SUCCESS) BNFree(r_bn); CTXFree(&ctx); return result; } int ELGAMAL_testSecret(ELGAMAL* a_elGroupKey, unsigned int a_uSelfMIXIdx, BIGNUM* a_bnSecret, unsigned int a_uMIXDecryptCnt, BIGNUM** a_bnF) { if ((a_elGroupKey == NULL) || (a_bnSecret == NULL) || (a_bnF == NULL)) return -1; if ((a_elGroupKey->g == NULL) || (a_elGroupKey->p == NULL)) return -1; int result = ELGAMAL_SUCCESS; BIGNUM* bnGSji = NULL; BIGNUM* tmp = NULL; BIGNUM* exp = NULL; BIGNUM* expPl = NULL; BN_CTX* ctx = NULL; BNInit(result, &bnGSji); BNInit(result, &tmp, 1); BNInit(result, &exp, a_uSelfMIXIdx + 1); BNInit(result, &expPl); CTXInit(result, &ctx); if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(bnGSji, a_elGroupKey->g, a_bnSecret, a_elGroupKey->p, ctx) == 0) result = ELGAMAL_ERROR; for (unsigned int l = 0; (l < a_uMIXDecryptCnt) && (result == ELGAMAL_SUCCESS); l++) { if (BN_set_word(expPl, l) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_exp(expPl, exp, expPl, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_exp(expPl, a_bnF[l], expPl, a_elGroupKey->p, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(tmp, tmp, expPl, a_elGroupKey->p, ctx) == 0) result = ELGAMAL_ERROR; } if (result == ELGAMAL_SUCCESS) if (BN_cmp(tmp, bnGSji) != 0) result = ELGAMAL_ERROR; CTXFree(&ctx); BNFree(&expPl); BNFree(&exp); BNFree(&tmp); BNFree(&bnGSji); return result; } unsigned int fac(unsigned int a_dValue) { if (a_dValue < 2) return 1; unsigned int result = 1; for (unsigned int i = 2; i <= a_dValue; i++) result *= i; return result; } int BN_neg(BIGNUM* ar_bn) { if (ar_bn == NULL) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; BIGNUM* bnM1 = NULL; BN_CTX* ctx = NULL; CTXInit(result, &ctx); if (BN_dec2bn(&bnM1, "-1") == 0) result = ELGAMAL_ERROR; else if (BN_mul(ar_bn, ar_bn, bnM1, ctx) == 0) result = ELGAMAL_ERROR; BNFree(&bnM1); CTXFree(&ctx); return result; } int ELGAMAL_calcSharedExp(BIGNUM** r_bnExp, unsigned int MIXCNT, unsigned int a_uListSize, unsigned int* a_uDecryptList, unsigned int a_uSelfIdx, BIGNUM* a_bnSecret, BIGNUM* a_bnModulo) { if ((r_bnExp == NULL) || (a_bnSecret == NULL) || (a_bnModulo == NULL)) return ELGAMAL_ERROR; int result = ELGAMAL_SUCCESS; int num = -1; int denom = 1; unsigned int uIdx = a_uSelfIdx + 1; BIGNUM* bnNum = NULL; BIGNUM* bnDenom = NULL; BN_CTX* ctx = NULL; BNFree(r_bnExp); BNInit(result, r_bnExp); BNInit(result, &bnNum); BNInit(result, &bnDenom); CTXInit(result, &ctx); for (unsigned int i = 1; (i <= MIXCNT) && (result == ELGAMAL_SUCCESS); i++) { if (i == uIdx) continue; if (getListIdx(a_uListSize, a_uDecryptList, i-1) < 0) continue; num = num * (-i); denom = denom * (uIdx - i); } if (num < 0) { if (BN_set_word(bnNum, num*-1) == 0) result = ELGAMAL_ERROR; else result = BN_neg(bnNum); } else if (BN_set_word(bnNum, num) == 0) result = ELGAMAL_ERROR; if (denom < 0) { if (BN_set_word(bnDenom, denom * -1) == 0) result = ELGAMAL_ERROR; else result = BN_neg(bnDenom); } else if (BN_set_word(bnDenom, denom) == 0) result = ELGAMAL_ERROR; /* if (BN_set_word(bnNum, fac(MIXCNT)/uIdx) == 0) result = ELGAMAL_ERROR; if (BN_set_word(bnDenom, fac(uIdx - 1) * fac(MIXCNT - uIdx)) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if ((MIXCNT & 0x01) > 0) result = BN_neg(bnNum); if (result == ELGAMAL_SUCCESS) if (((MIXCNT - uIdx) & 0x01) > 0) result = BN_neg(bnDenom);*/ if (result == ELGAMAL_SUCCESS) if (BN_nnmod(bnDenom, bnDenom, a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_inverse(bnDenom, bnDenom, a_bnModulo, ctx) == NULL) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(*r_bnExp, a_bnSecret, bnNum, a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; if (result == ELGAMAL_SUCCESS) if (BN_mod_mul(*r_bnExp, *r_bnExp, bnDenom, a_bnModulo, ctx) == 0) result = ELGAMAL_ERROR; BNClearFree(&bnNum); BNClearFree(&bnDenom); CTXFree(&ctx); return result; } anon-proxy-00.05.38+20081230/FlashMix/CABulletinBoard.hpp0000644000175000017500000000537310170075440021100 0ustar daviddavid#ifndef __CABULLETINBOARD__ #define __CABULLETINBOARD__ #include "../CAThread.hpp" #include "../CASocket.hpp" #include "../CASocketAddrINet.hpp" #include "../CAMutex.hpp" #include "../CAMsg.hpp" #include "uBubbleSort.hpp" #include "elgamal.hpp" #include "CABNSend.hpp" #include "FlashMIXGlobal.hpp" #include "CAMainThread.hpp" class CABulletinBoard : public CAMainThread { public: CABulletinBoard( UINT32 a_uPort, UINT32 a_uKeyLength, UINT32 a_uMIXCnt, UINT32 a_uMIXPermCnt, UINT32 a_uMIXDecryptCnt, UINT32 a_uAnonCnt); ~CABulletinBoard(); SINT32 init(); private: UINT32 m_uKeyLength; UINT32 m_uMIXCnt; UINT32 m_uMIXPermCnt; UINT32 m_uMIXDecryptCnt; ELGAMAL* m_elSignKey; ELGAMAL* m_elEncKey; ELGAMAL* m_elGroupKey; // MIX Data MIXDATA** m_vMIXData; CAMutex* m_pMutexMIXData; // user messages BIGNUM** m_vBNUserMsg; UINT32 m_uAnonCnt; // size of anonymity-set UINT32 m_uAnonListSize; // size of the msg-list UINT32 m_uUserMsgListPtr; // pointer to next free place CAMutex* m_pMutexUserMsg; // the mutex for the array SINT32 insertToUserList(BIGNUM* a_bnA, BIGNUM* a_bnB); SINT32 insertToUserList(SINT32& ar_sResult, BIGNUM* a_bnA, BIGNUM* a_bnB); SINT32 insertDummy(BIGNUM** ar_bnList, BIGNUM* a_bnDummyA, BIGNUM* a_bnDummyB); SINT32 insertDummy(SINT32& ar_sResult, BIGNUM** ar_bnList, BIGNUM* a_bnDummyA, BIGNUM* a_bnDummyB); static THREAD_RETURN handleRequest(void* a_req); static THREAD_RETURN keyShareing(void* a_thisPtr); static THREAD_RETURN mixProcess(void* a_thisPtr); static SINT32 initMix(CABulletinBoard* a_ths, CASocket* a_pClient); static SINT32 removeMix(CABulletinBoard* a_ths, CASocket* a_pClient); static SINT32 startKeyShareing(CABulletinBoard* a_ths); static SINT32 receiveUserData(CABulletinBoard* a_ths, CASocket* a_pClient); static SINT32 sendSignKey(CABulletinBoard* a_ths, CASocket* a_pClient); static SINT32 sendEncKey(CABulletinBoard* a_ths, CASocket* a_pClient); static SINT32 sendGroupKey(CABulletinBoard* a_ths, CASocket* a_pClient); static SINT32 createDummies(BIGNUM*** r_bnDummyList, CABulletinBoard* a_ths, CASocket** a_pSockets, UINT32* a_uPermList, UINT32 DUMMYCNT = 2); static SINT32 blind(BIGNUM*** r_bnFirstListFirstReenc, BIGNUM*** r_bnSecondListFirstReenc, BIGNUM*** r_bnFirstListSecondReenc, BIGNUM*** r_bnSecondListSecondReenc, CABulletinBoard* a_ths, CASocket** a_pSockets, UINT32* a_uPermList, BIGNUM** a_bnInputList); }; #endif // __CABULLETINBOARD__ anon-proxy-00.05.38+20081230/FlashMix/Array.hpp0000644000175000017500000000510710162311576017223 0ustar daviddavid#ifndef __ARRAY__ #define __ARRAY__ typedef void (*ARRAY_ELEMENT_INIT_FNC)(void **); typedef void (*ARRAY_ELEMENT_DELETE_FNC)(void *); template class Array { public: Array(); Array(int a_sSize); ~Array(); T* array(); int clear(); int size(); T get(int a_sIdx); int set(int a_sIdx, T a_value); int setInitFnc(ARRAY_ELEMENT_INIT_FNC a_fnc); int setDeleteFnc(ARRAY_ELEMENT_DELETE_FNC a_fnc); int setSize(int a_sSize); private: int m_sSize; T* m_pArr; ARRAY_ELEMENT_INIT_FNC m_fncInit; ARRAY_ELEMENT_DELETE_FNC m_fncDelete; int init(); }; template Array::Array() { m_sSize = -1; m_pArr = NULL; m_fncInit = NULL; m_fncDelete = NULL; } template Array::Array(int a_sSize) { m_sSize = -1; m_pArr = NULL; m_fncInit = NULL; m_fncDelete = NULL; setSize(a_sSize); } template T* Array::array() { return m_pArr; } template Array::~Array() { clear(); } template int Array::init() { if (m_fncInit == NULL) return 0; for (int i = 0; i < m_sSize; i++) m_fncInit((void**)&(m_pArr[i])); return 0; } template int Array::clear() { if (m_pArr == NULL) return 0; if (m_fncDelete != NULL) for (int i = 0; i < m_sSize; i++) m_fncDelete((void*)m_pArr[i]); delete[] m_pArr; m_pArr = NULL; m_sSize = -1; return 0; } template int Array::setInitFnc(ARRAY_ELEMENT_INIT_FNC a_fnc) { m_fncInit = a_fnc; return init(); } template int Array::setDeleteFnc(ARRAY_ELEMENT_DELETE_FNC a_fnc) { m_fncDelete = a_fnc; return 0; } template int Array::size() { return m_sSize; } template T Array::get(int a_sIdx) { if ((a_sIdx >= 0) && (a_sIdx < m_sSize)) return m_pArr[a_sIdx]; } template int Array::set(int a_sIdx, T a_value) { if ((a_sIdx < 0) || (a_sIdx >= m_sSize)) return -1; if (m_fncDelete != NULL) m_fncDelete((void*)m_pArr[a_sIdx]); m_pArr[a_sIdx] = a_value; return 0; } template int Array::setSize(int a_sSize) { if (a_sSize < 1) return -1; int result = 0; result = clear(); if (result == 0) if ((m_pArr = new T[a_sSize]) == NULL) result = -1; if (result == 0) result = init(); if (result == 0) m_sSize = a_sSize; return result; } #endif anon-proxy-00.05.38+20081230/FlashMix/FlashMix-lib.vcproj0000644000175000017500000002157410763776144021163 0ustar daviddavid anon-proxy-00.05.38+20081230/FlashMix/elgamal.hpp0000644000175000017500000000754210162311576017554 0ustar daviddavid#ifndef HEADER_ELGAMAL_H #define HEADER_ELGAMAL_H static const int ELGAMAL_SUCCESS = 1; static const int ELGAMAL_ERROR = 0; typedef struct elgamal_st ELGAMAL; struct elgamal_st { BIGNUM* p; // public save prime p = 2q + 1 BIGNUM* pm1; // p - 1 BIGNUM* q; // public prime q BIGNUM* g; // public generator of Gp (it holds: g^q mod p = 1) BIGNUM* x; // private key x BIGNUM* y; // public key y = g^x mod p }; ELGAMAL* ELGAMAL_new(void); void ELGAMAL_free(ELGAMAL* r); ELGAMAL* ELGAMAL_generate_key(int a_iBits); int ELGAMAL_isValidPublicKey(ELGAMAL* a_elKey); int ELGAMAL_isValidPrivateKey(ELGAMAL* a_elKey); // (a, b) = (m*y^alpha mod p, g^alpha mod p) // if r_bnEncA or r_bnEncB is NULL a new BIGNUM is created // 1 is returnd for success, 0 on error int ELGAMAL_encrypt(BIGNUM** r_bnEncA, BIGNUM** r_bnEncB, ELGAMAL* a_elKey, BIGNUM* a_bnAlpha, BIGNUM* a_bnMsg); int ELGAMAL_encrypt(BIGNUM** r_bnEncA, BIGNUM** r_bnEncB, ELGAMAL* a_elKey, BIGNUM* a_bnMsg); // encrypts a encrytped message with alpha // r_bnEncA and r_bnEncB is the encrypted Message and the return value int ELGAMAL_reencrypt(BIGNUM* r_bnEncA, BIGNUM* r_bnEncB, ELGAMAL* a_elKey, BIGNUM* a_bnAlpha); int ELGAMAL_reencrypt(BIGNUM** ar_bnList, ELGAMAL* a_elKey, unsigned int a_uListSize, BIGNUM** a_bnAlphaList); // generates an list of alphas which can be used for reencryption // 1 is returnd for succes, 0 on error int ELGAMAL_gen_exp(BIGNUM*** r_bnExp, ELGAMAL* a_elPublicKey, unsigned int a_uCount); // m = a*(b^x)^-1 mod p // if r_bnMsg is NULL a new BIGNUM is created // 1 is returnd for success, 0 on error int ELGAMAL_decrypt(BIGNUM** r_bnMsg, ELGAMAL* a_elKey, BIGNUM* a_bnEncA, BIGNUM* a_bnEncB); // (s, k) = ((m - x*k)*alpha^-1 mod p-1, g^alpha mod p) // !!! (p-1) mod alpha != 0 !!! // 1 is returned for success, 0 on error // if r_bnSignS or r_bnSignK is NULL a new BIGNUM is created int ELGAMAL_sign(BIGNUM** r_bnSignS, BIGNUM** r_bnSignK, ELGAMAL* a_elKey, BIGNUM* a_bnAlpha, BIGNUM* a_bnMsg); int ELGAMAL_sign(BIGNUM** r_bnSignS, BIGNUM** r_bnSignK, ELGAMAL* a_elKey, BIGNUM* a_bnMsg); // test: g^m mod p = y^k * k^s mod p // 1 if the condition holds, 0 if not and -1 on error int ELGAMAL_test_signature(ELGAMAL* a_elKey, BIGNUM* a_bnMsg, BIGNUM* a_bnSignS, BIGNUM* a_bnSignK); // generates the polynom of degree k - 1 // 1 is returned on success, 0 on error int ELGAMAL_choose_polynom(BIGNUM*** r_bnPolynom, unsigned int a_uDegree, ELGAMAL* a_elPublicSharedKey, BIGNUM* a_bnLocalSecret); // calculates Fij = g^fij // 1 is returned on success, 0 on error int ELGAMAL_calcF(BIGNUM*** r_bnF, ELGAMAL* a_elSharedGroupKey, unsigned int a_ufSize, BIGNUM** a_bnf); // calculates fi(j) // 1 is returned on success, 0 on error int ELGAMAL_calc_fij(BIGNUM** r_bn, BIGNUM* a_bnModulo, BIGNUM* a_bnJ, unsigned int a_ufSize, BIGNUM** a_bnf); int ELGAMAL_calc_allfij(BIGNUM*** r_bnfij, BIGNUM* a_bnModulo, unsigned int a_uMIXCnt, unsigned int a_ufSize, BIGNUM** a_bnf); // calculates si = SUM sji mod p // 1 is returned on success, 0 on error int ELGAMAL_calcSi(BIGNUM** r_bn, BIGNUM* a_bnModulo, unsigned int a_uSjiSize, BIGNUM** a_bnSi); // tests the received secret value from a MIX // 1 is returned if the condition g^sji = \prod F_{jl}^{i^l} holds, 0 if not, -1 on error int ELGAMAL_testSecret(ELGAMAL* a_elGroupKey, unsigned int a_uSelfMIXIdx, BIGNUM* a_bnSecret, unsigned int a_uMIXDecryptCnt, BIGNUM** a_bnF); // calculates the exponent for the shared decryption // 1 is returned on success, 0 on error int ELGAMAL_calcSharedExp(BIGNUM** r_bnExp, unsigned int MIXCNT, unsigned int a_uListSize, unsigned int* a_uDecryptList, unsigned int a_uSelfIdx, BIGNUM* a_bnSecret, BIGNUM* a_bnModulo); #endif // HEADER_ELGAMAL_H anon-proxy-00.05.38+20081230/FlashMix/CAFlashMix.hpp0000644000175000017500000001452510170075440020064 0ustar daviddavid#ifndef __CAFLASHMIX__ #define __CAFLASHMIX__ #include "../CAThread.hpp" #include "../CASocket.hpp" #include "../CASocketAddrINet.hpp" #include "../CAMsg.hpp" #include "elgamal.hpp" #include "CABNSend.hpp" #include "FlashMIXGlobal.hpp" #include "CAMainThread.hpp" static const UINT16 ROLE_PERM_SRV = 0; static const UINT16 ROLE_DECR_SRV = 1; class CAFlashMIX : public CAMainThread { public: CAFlashMIX( UINT8* a_uLocalIP, UINT32 a_uPort, UINT32 a_uPortKeyShare, UINT32 a_uPortDummy, UINT32 a_uPortBlind, UINT32 a_uPortBlindOK, UINT8* a_uBBIp, UINT32 a_uBBPort); ~CAFlashMIX(); SINT32 init(); SINT32 logout(); private: UINT8* m_uLocalIP; UINT32 m_uPortKeyShare; UINT32 m_uPortDummy; UINT32 m_uPortBlind; UINT32 m_uPortDecrypt; UINT32 m_uKeyLength; UINT32 m_uMIXCnt; UINT32 m_uMIXPermCnt; UINT32 m_uMIXDecryptCnt; ELGAMAL* m_elSignKey; ELGAMAL* m_elEncKey; ELGAMAL* m_elBBSignKey; ELGAMAL* m_elBBEncKey; ELGAMAL* m_elGroupKey; CASocketAddrINet* m_pAddrBB; // MIX Data MIXDATA** m_vMIXData; CAMutex* m_pMutexMIXData; // fills the m_vMIXData-List SINT32 receiveMIXData(SINT32& ar_sResult, CASocket* a_pClient); // receives the F and s Values of all mixes SINT32 receiveMIXValues(SINT32& ar_sResult, BIGNUM*** r_bnAllF, BIGNUM*** r_bnAllSj, BIGNUM** a_bnF, BIGNUM** a_bnSi); // sends the F and s values of this mix SINT32 sendMIXValues(SINT32&ar_sResult, BIGNUM*** r_bnAllF, BIGNUM*** r_bnAllSj, BIGNUM** a_bnF, BIGNUM** a_bnSi); static THREAD_RETURN handleRequest(void* a_req); static SINT32 startKeyShare(CAFlashMIX* a_ths, CASocket* a_pClient); static SINT32 createDummies(CAFlashMIX* a_ths, CASocket* a_pClient, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList); static SINT32 blind(UINT32* r_uInpListsSize, BIGNUM*** r_bnInpList, UINT32** r_uInpPermLists, BIGNUM*** r_bnExp, CAFlashMIX* a_ths, CASocket* a_pClient, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList); static SINT32 mixProcess(CAFlashMIX* a_ths, CASocket* a_pClient); static SINT32 blindReceiveInpList(SINT32& ar_sResult, UINT32& r_uListSize, BIGNUM*** r_bnInpList, CAFlashMIX* a_ths, CASocket* a_pBBClient, CASocket* a_pPrevMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList); static SINT32 blindSendInpList(SINT32& ar_sResult, CAFlashMIX* a_ths, CASocket* a_pBBClient, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList, UINT32 a_uListSize, BIGNUM** a_bnList); static SINT32 blindReenc(SINT32& ar_sResult, BIGNUM*** r_bnExp, BIGNUM** ar_bnList, ELGAMAL* a_elGroupKey, UINT32 a_uListSize); static SINT32 permutate(SINT32& ar_sResult, BIGNUM** ar_bnList, UINT32 a_uListSize, UINT32* a_uPerm); static SINT32 unblind(CAFlashMIX* a_ths, CASocket* a_pBB, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uPermList, UINT32* a_uInpListsSize, BIGNUM*** a_bnInpList, UINT32** a_uInpPerm, BIGNUM*** a_bnExp); static SINT32 unblindSendReceiveDummyData(SINT32& ar_sResult, UINT32* ar_uDummies, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 MIXCNT, UINT32 LISTCNT, UINT32 DUMMYCNT, UINT32 REENCCNT, UINT32* a_uInpPermSize, UINT32** a_uInpPerm, UINT32 a_rReEnc); static SINT32 unblindSendReceiveDummyExp2ReEnc(SINT32& ar_sResult, BIGNUM*** r_bnExp2ReEnc, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, BIGNUM*** a_bnExp, UINT32* a_uDummyPerm, UINT32 MIXCNT, UINT32 LISTCNT, UINT32 DUMMYCNT, UINT32 REENCCNT, UINT32 explistsize); static SINT32 switchEncListElements(UINT32 a_uListSize, BIGNUM** ar_bnList, UINT32 a_uMsgIdx1, UINT32 a_uMsgIdx2); static SINT32 unblindCheck2Dummy(SINT32& ar_sResult, CAFlashMIX* a_ths, BIGNUM** a_bnL0R0, BIGNUM** a_bnL1R0, BIGNUM** a_bnL0R1, BIGNUM** a_bnL1R1, UINT32* a_uDummyPerm, BIGNUM** a_bnDummyExp, UINT32 MIXCNT, UINT32 MIXFAC, UINT32 LISTFAC, UINT32 DUMMYFAC, UINT32 REENCFAC); static SINT32 unblindCheckProd(SINT32& ar_sResult, CAFlashMIX* a_ths, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32* a_uInpListsSize, BIGNUM** a_bnInpFirstReEncList, BIGNUM** a_bnInpSecondReEncList, BIGNUM*** a_bnOutLists, BIGNUM*** a_bnExp, UINT32 MIXCNT, UINT32 LISTCNT, UINT32 DUMMYCNT, UINT32 REENCCNT); static SINT32 unblindCheckFirstReEnc(SINT32& ar_sResult, CAFlashMIX* a_ths, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 a_uInpListSize, BIGNUM** a_bnInpList, BIGNUM** a_bnFistList, BIGNUM** a_bnSecondList, UINT32** a_uInpPerm, BIGNUM*** a_bnExp, UINT32 MIXCNT); static SINT32 unblindFirstReEncPermData(SINT32& ar_sResult, UINT32** r_uPermList, CASocket* a_pPrevMIX, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 LISTSIZE, UINT32** a_uInpPerm, UINT32 MIXCNT); static SINT32 unblindFirstReEncExpList(SINT32& ar_sResult, BIGNUM*** r_bnExpList, CASocket* a_pPrevMix, CASocket* a_pNextMIX, UINT32 a_uSelfIdx, UINT32 LISTSIZE, BIGNUM*** a_bnExp, UINT32 MIXCNT); static SINT32 unblindPermutate(SINT32& ar_sResult, BIGNUM** ar_bnList, UINT32 a_uListSize, UINT32* a_uPerm); static SINT32 unblindCalcAkkPerm(SINT32& ar_sResult, UINT32** r_uPerm0, UINT32** r_uPerm1, UINT32* a_uPermList, UINT32 MIXCNT, UINT32 LISTSIZE); static SINT32 decrypt(CAFlashMIX* a_ths, CASocket* a_pBB); static SINT32 decryptConnectMIX(CASocket** r_pPrevMIX, CASocket** r_pNextMIX, CAFlashMIX* a_ths, UINT32 a_uSelfIdx, UINT32* a_uDecryptList); static SINT32 decryptSendMessage(SINT32& ar_sResult, BIGNUM* a_bnMsg); static SINT32 unblindCalcAkk(SINT32& ar_sResult, UINT32** r_uPerm0, UINT32** r_uPerm1, UINT32 LISTSIZE, UINT32* a_uPermList, UINT32 MIXCNT); static SINT32 unblindGetFirstL1NotInL2(SINT32& ar_sResult, UINT32& r_uElement, UINT32 a_uList1Size, UINT32* a_uList1, UINT32 a_uList2Size, UINT32* a_uList2); static SINT32 unblindPermSetPtr(UINT32& ar_uPtrL, UINT32& ar_uPtrH, UINT32 a_uListSize, UINT32* a_uPerm); static SINT32 unblindPermutateMsg(SINT32& ar_sResult, BIGNUM** ar_bnList, UINT32 a_uListSize, UINT32* a_uPerm); }; #endif // __CAFLASHMIX__ anon-proxy-00.05.38+20081230/FlashMix/uBubbleSort.hpp0000644000175000017500000000074110162311576020374 0ustar daviddavid#ifndef uBubbleSortH #define uBubbleSortH template void BubbleSort(BASE_TYPE *_Array, unsigned int _ArrayLength); #endif template void BubbleSort(BASE_TYPE *_Array, unsigned int _ArrayLength) { for (unsigned int i = _ArrayLength - 1; i > 0; i--) for (unsigned int j = 0; j < i; j++) if (_Array[j] > _Array[j + 1]) { BASE_TYPE tmp = _Array[j]; _Array[j] = _Array[j + 1]; _Array[j + 1] = tmp; } } anon-proxy-00.05.38+20081230/FlashMix/FlashMix.vcproj0000644000175000017500000002466710763776144020425 0ustar daviddavid anon-proxy-00.05.38+20081230/CAASyncControlChannel.hpp0000644000175000017500000000374310316732037020511 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #if 0 #ifndef _CAASYNCCONTROLCHANNEL_ #define _CAASYNCCONTROLCHANNEL_ #include "CAAbstractControlChannel.hpp" #include "CAQueue.hpp" /** An asynchronous control channel. This means, that every message is * placed in a queue. You can than read messages from this Queue * NOTE: NOT IMPLEMENTED YET! */ class CAASyncControlChannel : public CAAbstractControlChannel { public: SINT32 proccessMessage(UINT8* msg, UINT32 msglen); private: CAQueue m_pQueue; }; #endif #endifanon-proxy-00.05.38+20081230/TypeA/0000755000175000017500000000000011126517127014741 5ustar daviddavidanon-proxy-00.05.38+20081230/TypeA/CALastMixA.cpp0000644000175000017500000006311411126465764017351 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "../StdAfx.h" #ifndef ONLY_LOCAL_PROXY #include "CALastMixA.hpp" #include "../CALastMixChannelList.hpp" #include "../CASingleSocketGroup.hpp" #include "../CAPool.hpp" #include "../CACmdLnOptions.hpp" #ifdef HAVE_EPOLL #include "../CASocketGroupEpoll.hpp" #endif extern CACmdLnOptions* pglobalOptions; #ifdef LOG_CHANNEL //CAMsg::printMsg(LOG_DEBUG,"Channel time log format is as follows: Channel-ID,Channel Start [micros], Channel End [micros], Upload (bytes), Download (bytes), DataAndOpenAndClosePacketsFromUser, DataAndClosePacketsToUser\n"); #define MACRO_DO_LOG_CHANNEL(a)\ CAMsg::printMsg(LOG_DEBUG,#a ":%u,%Lu,%Lu,%u,%u,%u,%u\n",\ pChannelListEntry->channelIn,pChannelListEntry->timeCreated,pQueueEntry->timestamp_proccessing_end,\ pChannelListEntry->trafficInFromUser,pChannelListEntry->trafficOutToUser,\ pChannelListEntry->packetsDataInFromUser,pChannelListEntry->packetsDataOutToUser); #define MACRO_DO_LOG_CHANNEL_CLOSE_FROM_USER MACRO_DO_LOG_CHANNEL(1) #define MACRO_DO_LOG_CHANNEL_CLOSE_FROM_MIX MACRO_DO_LOG_CHANNEL(2) #endif SINT32 CALastMixA::loop() { #ifndef NEW_MIX_TYPE //CASocketList oSocketList; #ifdef DELAY_CHANNELS m_pChannelList->setDelayParameters( pglobalOptions->getDelayChannelUnlimitTraffic(), pglobalOptions->getDelayChannelBucketGrow(), pglobalOptions->getDelayChannelBucketGrowIntervall()); #endif #ifdef DELAY_CHANNELS_LATENCY m_pChannelList->setDelayLatencyParameters( pglobalOptions->getDelayChannelLatency()); #endif #ifdef HAVE_EPOLL CASocketGroupEpoll* psocketgroupCacheRead=new CASocketGroupEpoll(false); CASocketGroupEpoll* psocketgroupCacheWrite=new CASocketGroupEpoll(true); #else CASocketGroup* psocketgroupCacheRead=new CASocketGroup(false); CASocketGroup* psocketgroupCacheWrite=new CASocketGroup(true); #endif tQueueEntry* pQueueEntry=new tQueueEntry; MIXPACKET* pMixPacket=&pQueueEntry->packet; SINT32 ret; SINT32 countRead; lmChannelListEntry* pChannelListEntry; UINT8 rsaBuff[RSA_SIZE]; UINT8* tmpBuff=new UINT8[MIXPACKET_SIZE]; bool bAktiv; m_logUploadedPackets=m_logDownloadedPackets=0; set64((UINT64&)m_logUploadedBytes,(UINT32)0); set64((UINT64&)m_logDownloadedBytes,(UINT32)0); CAThread* pLogThread=new CAThread((UINT8*)"CALastMixA - LogLoop"); pLogThread->setMainLoop(lm_loopLog); pLogThread->start(this); #ifdef LOG_CHANNEL CAMsg::printMsg(LOG_DEBUG,"Channel time log format is as follows: Channel-ID,Channel Start [micros], Channel End [micros], Upload (bytes), Download (bytes), DataAndOpenPacketsFromUser, DataPacketsToUser\n"); #endif while(!m_bRestart) { bAktiv=false; //Step 1a reading from previous Mix --> now in separate thread //Step 1b processing MixPackets from previous mix // processing maximal number of current channels packets if(m_pQueueReadFromMix->getSize()>=sizeof(tQueueEntry)) { bAktiv=true; UINT32 channels=m_pChannelList->getSize()+1; for(UINT32 k=0;kgetSize()>=sizeof(tQueueEntry);k++) { ret=sizeof(tQueueEntry); m_pQueueReadFromMix->get((UINT8*)pQueueEntry,(UINT32*)&ret); #if defined(LOG_PACKET_TIMES) ||defined(LOG_CHANNEL) getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_start); #endif #ifdef LOG_PACKET_TIMES set64(pQueueEntry->timestamp_proccessing_start,pQueueEntry->timestamp_proccessing_start_OP); #endif if(pMixPacket->channel>0&&pMixPacket->channel<256) { m_pMuxInControlChannelDispatcher->proccessMixPacket(pMixPacket); continue; } // one packet received m_logUploadedPackets++; pChannelListEntry=m_pChannelList->get(pMixPacket->channel); if(pChannelListEntry==NULL) { if(pMixPacket->flags==CHANNEL_OPEN) { #if defined(_DEBUG) CAMsg::printMsg(LOG_DEBUG,"New Connection from previous Mix!\n"); #endif m_pRSA->decrypt(pMixPacket->data,rsaBuff); #ifdef REPLAY_DETECTION // replace time(NULL) with the real timestamp () // packet-timestamp + m_u64ReferenceTime UINT32 stamp=((UINT32)(rsaBuff[13]<<16)+(UINT32)(rsaBuff[14]<<8)+(UINT32)(rsaBuff[15]))*REPLAY_BASE; if(m_pReplayDB->insert(rsaBuff,stamp+m_u64ReferenceTime)!=E_SUCCESS) // if(m_pReplayDB->insert(rsaBuff,time(NULL))!=E_SUCCESS) { CAMsg::printMsg(LOG_INFO,"Replay: Duplicate packet ignored.\n"); continue; } #endif CASymCipher* newCipher=new CASymCipher(); newCipher->setKey(rsaBuff); newCipher->crypt1(pMixPacket->data+RSA_SIZE, pMixPacket->data+RSA_SIZE-KEY_SIZE, DATA_SIZE-RSA_SIZE); memcpy( pMixPacket->data,rsaBuff+KEY_SIZE, RSA_SIZE-KEY_SIZE); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif CASocket* tmpSocket=new CASocket; CACacheLoadBalancing* ptmpLB=m_pCacheLB; ret=E_UNKNOWN; if(pMixPacket->payload.type==MIX_PAYLOAD_SOCKS) ptmpLB=m_pSocksLB; for(UINT32 count=0;countgetElementCount();count++) { tmpSocket->create(); tmpSocket->setRecvBuff(50000); tmpSocket->setSendBuff(5000); ret=tmpSocket->connect(*ptmpLB->get(),LAST_MIX_TO_PROXY_CONNECT_TIMEOUT); if(ret==E_SUCCESS) break; tmpSocket->close(); } if(ret!=E_SUCCESS) { #if defined (_DEBUG) || defined (DELAY_CHANNELS_LATENCY) CAMsg::printMsg(LOG_DEBUG,"Cannot connect to Squid!\n"); #endif delete tmpSocket; tmpSocket = NULL; /* send a close packet signaling the connect error */ getRandom(pMixPacket->payload.data, PAYLOAD_SIZE); pMixPacket->payload.type = CONNECTION_ERROR_FLAG; pMixPacket->payload.len = 0; pMixPacket->flags = CHANNEL_CLOSE; newCipher->crypt2(pMixPacket->data, pMixPacket->data, DATA_SIZE); #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif m_pQueueSendToMix->add(pQueueEntry,sizeof(tQueueEntry)); m_logDownloadedPackets++; delete newCipher; newCipher = NULL; } else { //connection to proxy successful UINT16 payLen=ntohs(pMixPacket->payload.len); #ifdef _DEBUG UINT8 c=pMixPacket->payload.data[30]; pMixPacket->payload.data[30]=0; CAMsg::printMsg(LOG_DEBUG,"Try sending data to Squid: %s\n",pMixPacket->payload.data); pMixPacket->payload.data[30]=c; #endif #ifdef LOG_CRIME if(payLen<=PAYLOAD_SIZE&&checkCrime(pMixPacket->payload.data,payLen)) { UINT8 crimeBuff[PAYLOAD_SIZE+1]; tQueueEntry oSigCrimeQueueEntry; memset(&oSigCrimeQueueEntry,0,sizeof(tQueueEntry)); memset(crimeBuff,0,PAYLOAD_SIZE+1); memcpy(crimeBuff,pMixPacket->payload.data,payLen); UINT32 id=m_pMuxIn->sigCrime(pMixPacket->channel,&oSigCrimeQueueEntry.packet); m_pQueueSendToMix->add(&oSigCrimeQueueEntry,sizeof(tQueueEntry)); int log=LOG_ENCRYPTED; if(!pglobalOptions->isEncryptedLogEnabled()) log=LOG_CRIT; CAMsg::printMsg(log,"Crime detected -- ID: %u -- Content: \n%s\n",id,crimeBuff); } #endif if(payLen>PAYLOAD_SIZE||tmpSocket->sendTimeOut(pMixPacket->payload.data,payLen,LAST_MIX_TO_PROXY_SEND_TIMEOUT)==SOCKET_ERROR) { #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"Error sending Data to Squid!\n"); #endif tmpSocket->close(); delete tmpSocket; tmpSocket = NULL; /* send a close packet signaling the connect error */ getRandom(pMixPacket->payload.data, PAYLOAD_SIZE); pMixPacket->payload.type = 0; pMixPacket->payload.len = htons(CONNECTION_ERROR_FLAG); pMixPacket->flags = CHANNEL_CLOSE; newCipher->crypt2(pMixPacket->data, pMixPacket->data, DATA_SIZE); #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif m_pQueueSendToMix->add(pQueueEntry,sizeof(tQueueEntry)); m_logDownloadedPackets++; delete newCipher; newCipher = NULL; } else { tmpSocket->setNonBlocking(true); #if defined (DELAY_CHANNELS_LATENCY) UINT64 u64temp; getcurrentTimeMillis(u64temp); #endif CAQueue* pQueue=new CAQueue(PAYLOAD_SIZE); #ifdef LASTMIX_CHECK_MEMORY pQueue->logIfSizeGreaterThen(100000); #endif m_pChannelList->add(pMixPacket->channel,tmpSocket,newCipher,pQueue #if defined (LOG_CHANNEL) ,pQueueEntry->timestamp_proccessing_start,payLen #endif #if defined (DELAY_CHANNELS_LATENCY) ,u64temp #endif ); #ifdef HAVE_EPOLL psocketgroupCacheRead->add(*tmpSocket,m_pChannelList->get(pMixPacket->channel)); #else psocketgroupCacheRead->add(*tmpSocket); #endif #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end); m_pLogPacketStats->addToTimeingStats(*pQueueEntry,CHANNEL_OPEN,true); #endif #ifdef DATA_RETENTION_LOG pQueueEntry->dataRetentionLogEntry.t_out=time(NULL); pQueueEntry->dataRetentionLogEntry.entity.last.port_out=tmpSocket->getLocalPort(); tmpSocket->getLocalIP(pQueueEntry->dataRetentionLogEntry.entity.last.ip_out); m_pDataRetentionLog->log(&pQueueEntry->dataRetentionLogEntry); #endif } } } } else {//channellist entry !=NULL if(pMixPacket->flags==CHANNEL_CLOSE) { psocketgroupCacheRead->remove(*(pChannelListEntry->pSocket)); psocketgroupCacheWrite->remove(*(pChannelListEntry->pSocket)); pChannelListEntry->pSocket->close(); delete pChannelListEntry->pSocket; pChannelListEntry->pSocket = NULL; delete pChannelListEntry->pCipher; pChannelListEntry->pCipher = NULL; delete pChannelListEntry->pQueueSend; pChannelListEntry->pQueueSend = NULL; #if defined (LOG_PACKET_TIMES) ||defined (LOG_CHANNEL) getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end); #endif #if defined (LOG_PACKET_TIMES) set64(pQueueEntry->timestamp_proccessing_end_OP,pQueueEntry->timestamp_proccessing_end); m_pLogPacketStats->addToTimeingStats(*pQueueEntry,CHANNEL_CLOSE,true); #endif #ifdef LOG_CHANNEL pChannelListEntry->packetsDataInFromUser++; MACRO_DO_LOG_CHANNEL_CLOSE_FROM_USER #endif m_pChannelList->removeChannel(pMixPacket->channel); } else if(pMixPacket->flags==CHANNEL_SUSPEND) { #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"Suspending channel %u Socket: %u\n",pMixPacket->channel,(SOCKET)(*pChannelListEntry->pSocket)); #endif psocketgroupCacheRead->remove(*(pChannelListEntry->pSocket)); } else if(pMixPacket->flags==CHANNEL_RESUME) { #ifdef _DEBUG CAMsg::printMsg(LOG_DEBUG,"Resuming channel %u Socket: %u\n",pMixPacket->channel,(SOCKET)(*pChannelListEntry->pSocket)); #endif #ifdef HAVE_EPOLL psocketgroupCacheRead->add(*(pChannelListEntry->pSocket),pChannelListEntry); #else psocketgroupCacheRead->add(*(pChannelListEntry->pSocket)); #endif } else if(pMixPacket->flags==CHANNEL_DATA) { #ifdef LOG_CHANNEL pChannelListEntry->packetsDataInFromUser++; #endif pChannelListEntry->pCipher->crypt1(pMixPacket->data,pMixPacket->data,DATA_SIZE); ret=ntohs(pMixPacket->payload.len); #ifdef NEW_FLOW_CONTROL if(ret&NEW_FLOW_CONTROL_FLAG) { pChannelListEntry->sendmeCounter=max(0,pChannelListEntry->sendmeCounter-FLOW_CONTROL_SENDME_SOFT_LIMIT); ret&=(!NEW_FLOW_CONTROL_FLAG); } #endif if(ret>=0&&ret<=PAYLOAD_SIZE) { #ifdef LOG_CHANNEL pChannelListEntry->trafficInFromUser+=ret; #endif #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif ret=pChannelListEntry->pQueueSend->add(pMixPacket->payload.data,ret); } else ret=SOCKET_ERROR; if(ret==SOCKET_ERROR) { psocketgroupCacheRead->remove(*(pChannelListEntry->pSocket)); psocketgroupCacheWrite->remove(*(pChannelListEntry->pSocket)); pChannelListEntry->pSocket->close(); delete pChannelListEntry->pSocket; pChannelListEntry->pSocket = NULL; delete pChannelListEntry->pCipher; pChannelListEntry->pCipher = NULL; /* now send channel-close */ delete pChannelListEntry->pQueueSend; pChannelListEntry->pQueueSend = NULL; #ifdef LOG_CHANNEL pChannelListEntry->packetsDataOutToUser++; getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end); MACRO_DO_LOG_CHANNEL_CLOSE_FROM_MIX #endif m_pChannelList->removeChannel(pMixPacket->channel); getRandom(pMixPacket->data,DATA_SIZE); pMixPacket->flags=CHANNEL_CLOSE; #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif m_pQueueSendToMix->add(pQueueEntry,sizeof(tQueueEntry)); m_logDownloadedPackets++; } else { #ifdef HAVE_EPOLL psocketgroupCacheWrite->add(*(pChannelListEntry->pSocket),pChannelListEntry); #else psocketgroupCacheWrite->add(*(pChannelListEntry->pSocket)); #endif #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end); m_pLogPacketStats->addToTimeingStats(*pQueueEntry,CHANNEL_DATA,true); #endif } } } } } //end Step 1 //Step 2 Sending to Cache... countRead=psocketgroupCacheWrite->select(0); if(countRead>0) { bAktiv=true; #ifdef HAVE_EPOLL pChannelListEntry=(lmChannelListEntry*)psocketgroupCacheWrite->getFirstSignaledSocketData(); while(pChannelListEntry!=NULL) { #else pChannelListEntry=m_pChannelList->getFirstSocket(); while(pChannelListEntry!=NULL&&countRead>0) { if(psocketgroupCacheWrite->isSignaled(*(pChannelListEntry->pSocket))) { countRead--; #endif SINT32 len=MIXPACKET_SIZE; pChannelListEntry->pQueueSend->peek(tmpBuff,(UINT32*)&len); len=pChannelListEntry->pSocket->send(tmpBuff,len); if(len>0) { add64((UINT64&)m_logUploadedBytes,len); pChannelListEntry->pQueueSend->remove((UINT32*)&len); if(pChannelListEntry->pQueueSend->isEmpty()) { psocketgroupCacheWrite->remove(*(pChannelListEntry->pSocket)); } } else { if(len==SOCKET_ERROR) { //do something if send error psocketgroupCacheRead->remove(*(pChannelListEntry->pSocket)); psocketgroupCacheWrite->remove(*(pChannelListEntry->pSocket)); pChannelListEntry->pSocket->close(); delete pChannelListEntry->pSocket; pChannelListEntry->pSocket = NULL; delete pChannelListEntry->pCipher; pChannelListEntry->pCipher = NULL; /* now send channel-close */ delete pChannelListEntry->pQueueSend; pChannelListEntry->pQueueSend = NULL; pMixPacket->flags=CHANNEL_CLOSE; getRandom(pMixPacket->data,DATA_SIZE); pMixPacket->channel=pChannelListEntry->channelIn; #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif m_pQueueSendToMix->add(pQueueEntry,sizeof(tQueueEntry)); m_logDownloadedPackets++; #ifdef LOG_CHANNEL pChannelListEntry->packetsDataOutToUser++; #endif #ifdef LOG_CHANNEL getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end); MACRO_DO_LOG_CHANNEL_CLOSE_FROM_MIX #endif m_pChannelList->removeChannel(pChannelListEntry->channelIn); } } #ifdef HAVE_EPOLL pChannelListEntry=(lmChannelListEntry*)psocketgroupCacheWrite->getNextSignaledSocketData(); #else } pChannelListEntry=m_pChannelList->getNextSocket(); #endif } } //End Step 2 //Step 3 Reading from Cache.... countRead=psocketgroupCacheRead->select(0); #ifdef DELAY_CHANNELS_LATENCY UINT64 current_time_millis; getcurrentTimeMillis(current_time_millis); #endif if(countRead>0&&m_pQueueSendToMix->getSize()getFirstSignaledSocketData(); while(pChannelListEntry!=NULL) { #else pChannelListEntry=m_pChannelList->getFirstSocket(); while(pChannelListEntry!=NULL&&countRead>0) { if(psocketgroupCacheRead->isSignaled(*(pChannelListEntry->pSocket))) { countRead--; #endif #if defined(DELAY_CHANNELS)||defined(DELAY_CHANNELS_LATENCY)||defined(NEW_FLOW_CONTROL) #define NEED_IF_12 #endif #ifdef NEED_IF_12 if(true #endif #ifdef DELAY_CHANNELS &&(m_pChannelList->hasDelayBuckets(pChannelListEntry->delayBucketID) ) #endif #ifdef DELAY_CHANNELS_LATENCY &&(isGreater64(current_time_millis,pChannelListEntry->timeLatency)) #endif #ifdef NEW_FLOW_CONTROL &&(pChannelListEntry->sendmeCounterpSocket->receive(pMixPacket->payload.data,PAYLOAD_SIZE); #else UINT32 readLen= min( m_pChannelList->getDelayBuckets(pChannelListEntry->delayBucketID), PAYLOAD_SIZE); ret=pChannelListEntry->pSocket->receive(pMixPacket->payload.data,readLen); #endif #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_start); set64(pQueueEntry->timestamp_proccessing_start_OP,pQueueEntry->timestamp_proccessing_start); #endif if(ret==SOCKET_ERROR||ret==0) { psocketgroupCacheRead->remove(*(pChannelListEntry->pSocket)); psocketgroupCacheWrite->remove(*(pChannelListEntry->pSocket)); pChannelListEntry->pSocket->close(); delete pChannelListEntry->pSocket; pChannelListEntry->pSocket = NULL; /* send channel-close */ delete pChannelListEntry->pCipher; pChannelListEntry->pCipher = NULL; delete pChannelListEntry->pQueueSend; pChannelListEntry->pQueueSend = NULL; pMixPacket->flags=CHANNEL_CLOSE; pMixPacket->channel=pChannelListEntry->channelIn; getRandom(pMixPacket->data,DATA_SIZE); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif m_pQueueSendToMix->add(pQueueEntry,sizeof(tQueueEntry)); m_logDownloadedPackets++; #ifdef LOG_CHANNEL pChannelListEntry->packetsDataOutToUser++; #endif #ifdef LOG_CHANNEL getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end); MACRO_DO_LOG_CHANNEL_CLOSE_FROM_MIX #endif m_pChannelList->removeChannel(pChannelListEntry->channelIn); } else { add64((UINT64&)m_logDownloadedBytes,ret); #if defined(LOG_CHANNEL) pChannelListEntry->trafficOutToUser+=ret; #endif #ifdef DELAY_CHANNELS m_pChannelList->reduceDelayBuckets(pChannelListEntry->delayBucketID, ret); #endif pMixPacket->channel=pChannelListEntry->channelIn; pMixPacket->flags=CHANNEL_DATA; pMixPacket->payload.type=0; #ifdef NEW_FLOW_CONTROL if(pChannelListEntry->sendmeCounter==FLOW_CONTROL_SENDME_SOFT_LIMIT) { pMixPacket->payload.len=htons((UINT16)ret|NEW_FLOW_CONTROL_FLAG); CAMsg::printMsg(LOG_DEBUG,"Send sendme request\n"); } else pMixPacket->payload.len=htons((UINT16)ret); #else pMixPacket->payload.len=htons((UINT16)ret); #endif pChannelListEntry->pCipher->crypt2(pMixPacket->data,pMixPacket->data,DATA_SIZE); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif m_pQueueSendToMix->add(pQueueEntry, sizeof(tQueueEntry)); m_logDownloadedPackets++; #if defined(LOG_CHANNEL) pChannelListEntry->packetsDataOutToUser++; #endif #ifdef NEW_FLOW_CONTROL pChannelListEntry->sendmeCounter++; #endif } } #ifdef HAVE_EPOLL pChannelListEntry=(lmChannelListEntry*)psocketgroupCacheRead->getNextSignaledSocketData(); #else } pChannelListEntry=m_pChannelList->getNextSocket(); #endif } } //end Step 3 //Step 4 Writing to previous Mix // Now in a separate Thread! // //end step 4 if(!bAktiv) msSleep(100); } //ERR: CAMsg::printMsg(LOG_CRIT,"Seems that we are restarting now!!\n"); m_bRunLog=false; //clean(); delete []tmpBuff; tmpBuff = NULL; delete pQueueEntry; pQueueEntry = NULL; pLogThread->join(); delete pLogThread; pLogThread = NULL; delete psocketgroupCacheWrite; psocketgroupCacheWrite = NULL; delete psocketgroupCacheRead; psocketgroupCacheRead = NULL; #endif //! NEW_MIX_TYPE return E_UNKNOWN; } #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/TypeA/Makefile.in0000644000175000017500000003064111126501051016777 0ustar daviddavid# Makefile.in generated by automake 1.10.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Autoconfiguration files for proxytest (a MiX proxy) # Konrad Rieck # VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = TypeA DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libmixa_a_AR = $(AR) $(ARFLAGS) libmixa_a_LIBADD = am_libmixa_a_OBJECTS = CAFirstMixA.$(OBJEXT) CALastMixA.$(OBJEXT) libmixa_a_OBJECTS = $(am_libmixa_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libmixa_a_SOURCES) DIST_SOURCES = $(libmixa_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBCPPUNIT = @LIBCPPUNIT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign noinst_LIBRARIES = libmixa.a libmixa_a_SOURCES = CAFirstMixA.cpp CAFirstMixA.hpp CALastMixA.cpp CALastMixA.hpp includes = @INCLUDES@ all: all-am .SUFFIXES: .SUFFIXES: .cpp .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign TypeA/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign TypeA/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libmixa.a: $(libmixa_a_OBJECTS) $(libmixa_a_DEPENDENCIES) -rm -f libmixa.a $(libmixa_a_AR) libmixa.a $(libmixa_a_OBJECTS) $(libmixa_a_LIBADD) $(RANLIB) libmixa.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CAFirstMixA.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CALastMixA.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-exec-am: install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: anon-proxy-00.05.38+20081230/TypeA/Makefile.old0000644000175000017500000000043611122436452017156 0ustar daviddavidlibmixa.a: CAFirstMixA.cpp CAFirstMixA.hpp CALastMixA.hpp CALastMixA.cpp $(CC) -c $(CPPFLAGS) $(INCLUDE) $(DEBUG) CALastMixA.cpp -o CALastMixA.o $(CC) -c $(CPPFLAGS) $(INCLUDE) $(DEBUG) CAFirstMixA.cpp -o CAFirstMixA.o ar -rcs libmixa.a *.o clean: rm -f *.o rm -f libmixa.a anon-proxy-00.05.38+20081230/TypeA/CAFirstMixA.cpp0000644000175000017500000010257111126516211017516 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "../StdAfx.h" #ifndef ONLY_LOCAL_PROXY #include "CAFirstMixA.hpp" #include "../CAThread.hpp" #include "../CASingleSocketGroup.hpp" #include "../CAInfoService.hpp" #include "../CAPool.hpp" #include "../CACmdLnOptions.hpp" #include "../CAAccountingInstance.hpp" #include "../CAStatusManager.hpp" #ifdef HAVE_EPOLL #include "../CASocketGroupEpoll.hpp" #endif extern CACmdLnOptions* pglobalOptions; void CAFirstMixA::shutDown() { m_bIsShuttingDown = true; #ifdef PAYMENT UINT32 connectionsClosed = 0; fmHashTableEntry* timeoutHashEntry; if(m_pInfoService != NULL) { CAMsg::printMsg(LOG_DEBUG,"Shutting down infoservice.\n"); m_pInfoService->stop(); } if(m_pChannelList!=NULL) // may happen if mixes did not yet connect to each other { while ((timeoutHashEntry = m_pChannelList->popTimeoutEntry(true)) != NULL) { CAMsg::printMsg(LOG_DEBUG,"Shutting down, closing client connection.\n"); connectionsClosed++; closeConnection(timeoutHashEntry); } CAMsg::printMsg(LOG_DEBUG,"Closed %i client connections.\n", connectionsClosed); } #endif m_bRestart = true; m_bIsShuttingDown = false; } SINT32 CAFirstMixA::closeConnection(fmHashTableEntry* pHashEntry) { if (pHashEntry == NULL) { return E_UNKNOWN; } INIT_STACK; BEGIN_STACK("CAFirstMixA::closeConnection"); fmChannelListEntry* pEntry; tQueueEntry* pQueueEntry = new tQueueEntry; MIXPACKET* pMixPacket=&pQueueEntry->packet; #ifdef LOG_TRAFFIC_PER_USER UINT64 current_time; getcurrentTimeMillis(current_time); CAMsg::printMsg(LOG_DEBUG,"Removing Connection wiht ID: %Lu -- login time [ms] %Lu -- logout time [ms] %Lu -- Traffic was: IN: %u -- OUT: %u\n",pHashEntry->id,pHashEntry->timeCreated,current_time,pHashEntry->trafficIn,pHashEntry->trafficOut); #endif m_pIPList->removeIP(pHashEntry->peerIP); m_psocketgroupUsersRead->remove(*(CASocket*)pHashEntry->pMuxSocket); m_psocketgroupUsersWrite->remove(*(CASocket*)pHashEntry->pMuxSocket); pEntry = m_pChannelList->getFirstChannelForSocket(pHashEntry->pMuxSocket); while(pEntry!=NULL) { getRandom(pMixPacket->data,DATA_SIZE); pMixPacket->flags=CHANNEL_CLOSE; pMixPacket->channel=pEntry->channelOut; #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif m_pQueueSendToMix->add(pQueueEntry, sizeof(tQueueEntry)); delete pEntry->pCipher; pEntry->pCipher = NULL; pEntry=m_pChannelList->getNextChannel(pEntry); } ASSERT(pHashEntry->pQueueSend!=NULL,"Send queue is NULL"); delete pHashEntry->pQueueSend; pHashEntry->pQueueSend = NULL; delete pHashEntry->pSymCipher; pHashEntry->pSymCipher = NULL; #ifdef COUNTRY_STATS decUsers(pHashEntry); #else decUsers(); #endif CAMuxSocket* pMuxSocket = pHashEntry->pMuxSocket; // Save the socket - its pointer will be deleted in this method!!! Crazy mad programming... m_pChannelList->remove(pHashEntry->pMuxSocket); delete pMuxSocket; pMuxSocket = NULL; pHashEntry->pMuxSocket = NULL; // not needed now, but maybe in the future... delete pQueueEntry; pQueueEntry = NULL; FINISH_STACK("CAFirstMixA::closeConnection"); return E_SUCCESS; } SINT32 CAFirstMixA::loop() { #ifndef NEW_MIX_TYPE #ifdef DELAY_USERS m_pChannelList->setDelayParameters( pglobalOptions->getDelayChannelUnlimitTraffic(), pglobalOptions->getDelayChannelBucketGrow(), pglobalOptions->getDelayChannelBucketGrowIntervall()); #endif // CASingleSocketGroup osocketgroupMixOut; SINT32 countRead; //#ifdef LOG_PACKET_TIMES // tPoolEntry* pPoolEntry=new tPoolEntry; // MIXPACKET* pMixPacket=&pPoolEntry->mixpacket; //#else tQueueEntry* pQueueEntry = new tQueueEntry; MIXPACKET* pMixPacket=&pQueueEntry->packet; //#endif m_nUser=0; SINT32 ret; //osocketgroupMixOut.add(*m_pMuxOut); UINT8* tmpBuff=new UINT8[sizeof(tQueueEntry)]; CAMsg::printMsg(LOG_DEBUG,"Starting Message Loop... \n"); bool bAktiv; UINT8 rsaBuff[RSA_SIZE]; #ifdef LOG_TRAFFIC_PER_USER UINT64 current_time; UINT32 diff_time; CAMsg::printMsg(LOG_DEBUG,"Channel log formats:\n"); CAMsg::printMsg(LOG_DEBUG,"1. Close received from user (times in micros) - 1:Channel-ID,Connection-ID,Channel open timestamp (microseconds),PacketsIn (only data and open),PacketsOut (only data),ChannelDuration (open packet received --> close packet put into send queue to next mix)\n"); CAMsg::printMsg(LOG_DEBUG,"2. Channel close from Mix(times in micros)- 2.:Channel-ID,Connection-ID,Channel open timestamp (microseconds),PacketsIn (only data and open), PacketsOut (only data),ChannelDuration (open packet received)--> close packet put into send queue to next user\n"); #endif /** @todo check if thread is closed */ #ifdef _DEBUG CAThread* pLogThread=new CAThread((UINT8*)"CAFirstMixA - LogLoop"); pLogThread->setMainLoop(fm_loopLog); pLogThread->start(this); #endif // CAThread threadReadFromUsers; // threadReadFromUsers.setMainLoop(loopReadFromUsers); // threadReadFromUsers.start(this); while(!m_bRestart) /* the main mix loop as long as there are things that are not handled by threads. */ { bAktiv=false; #ifdef PAYMENT // check the timeout for all connections fmHashTableEntry* timeoutHashEntry; while ((timeoutHashEntry = m_pChannelList->popTimeoutEntry()) != NULL) { if (timeoutHashEntry->bRecoverTimeout) { CAMsg::printMsg(LOG_DEBUG,"Client connection closed due to timeout.\n"); } else { // This should not happen if all client connections are closed as defined in the protocols. //#ifdef PAYMENT UINT32 authFlags = CAAccountingInstance::getAuthFlags(timeoutHashEntry); if (authFlags > 0) { CAMsg::printMsg(LOG_ERR,"Client connection closed due to forced timeout! Payment auth flags: %u\n", authFlags); } else //#endif { CAMsg::printMsg(LOG_ERR,"Client connection closed due to forced timeout!\n"); } } closeConnection(timeoutHashEntry); } #endif //LOOP_START: //First Step //Checking for new connections // Now in a separate Thread.... // Second Step // Checking for data from users // Now in a separate Thread (see loopReadFromUsers()) //Only proccess user data, if queue to next mix is not to long!! if(m_pQueueSendToMix->getSize()select(/*false,*/0); // how many JAP<->mix connections have received data from their coresponding JAP if(countRead>0) bAktiv=true; #ifdef HAVE_EPOLL //if we have epool we do not need to search the whole list //of connected JAPs to find the ones who have sent data //as epool will return ONLY these connections. fmHashTableEntry* pHashEntry=(fmHashTableEntry*)m_psocketgroupUsersRead->getFirstSignaledSocketData(); while(pHashEntry!=NULL) { CAMuxSocket* pMuxSocket=pHashEntry->pMuxSocket; #else //if we do not have epoll we have to go to the whole //list of open connections to find the ones which //actually have sent some data fmHashTableEntry* pHashEntry=m_pChannelList->getFirst(); while(pHashEntry!=NULL&&countRead>0) // iterate through all connections as long as there is at least one active left { CAMuxSocket* pMuxSocket=pHashEntry->pMuxSocket; if(m_psocketgroupUsersRead->isSignaled(*pMuxSocket)) // if this one seems to have data { countRead--; #endif /*#ifdef DELAY_USERS * Don't delay upstream if( m_pChannelList->hasDelayBuckets(pHashEntry->delayBucketID) ) { #endif*/ ret=pMuxSocket->receive(pMixPacket,0); #if defined LOG_PACKET_TIMES||defined(LOG_CHANNEL) getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_start); set64(pQueueEntry->timestamp_proccessing_start_OP,pQueueEntry->timestamp_proccessing_start); #endif #ifdef DATA_RETENTION_LOG pQueueEntry->dataRetentionLogEntry.t_in=time(NULL); #endif if(ret==SOCKET_ERROR/*||pHashEntry->accessUntilbRecoverTimeout) { // renew the timeout only if recovery is allowed m_pChannelList->pushTimeoutEntry(pHashEntry); } #endif #ifdef LOG_TRAFFIC_PER_USER pHashEntry->trafficIn++; #endif #ifdef COUNTRY_STATS m_PacketsPerCountryIN[pHashEntry->countryID].inc(); #endif //New control channel code...! if(pMixPacket->channel>0&&pMixPacket->channel<256) { if (pHashEntry->pControlChannelDispatcher->proccessMixPacket(pMixPacket)) { goto NEXT_USER; } else { CAMsg::printMsg(LOG_DEBUG, "Control channel packet is invalid and could not be processed!\n"); closeConnection(pHashEntry); goto NEXT_USER; } } #ifdef PAYMENT SINT32 ret = CAAccountingInstance::handleJapPacket(pHashEntry, false, false); if (CAAccountingInstance::HANDLE_PACKET_CONNECTION_OK == ret) { // renew the timeout pHashEntry->bRecoverTimeout = true; m_pChannelList->pushTimeoutEntry(pHashEntry); } else if (CAAccountingInstance::HANDLE_PACKET_HOLD_CONNECTION == ret) { // @todo this packet should be queued for later processing pHashEntry->bRecoverTimeout = false; } else if (CAAccountingInstance::HANDLE_PACKET_PREPARE_FOR_CLOSING_CONNECTION == ret) { // do not forward this packet pHashEntry->bRecoverTimeout = false; goto NEXT_USER; } else if (CAAccountingInstance::HANDLE_PACKET_CLOSE_CONNECTION == ret) { // kickout this user - he deserves it... closeConnection(pHashEntry); goto NEXT_USER; } #endif if(pMixPacket->flags==CHANNEL_DUMMY) // just a dummy to keep the connection alife in e.g. NAT gateways { CAMsg::printMsg(LOG_DEBUG,"received dummy traffic\n"); getRandom(pMixPacket->data,DATA_SIZE); #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif #ifdef LOG_TRAFFIC_PER_USER pHashEntry->trafficOut++; #endif #ifdef COUNTRY_STATS m_PacketsPerCountryOUT[pHashEntry->countryID].inc(); #endif pHashEntry->pQueueSend->add(pQueueEntry,sizeof(tQueueEntry)); #ifdef HAVE_EPOLL //m_psocketgroupUsersWrite->add(*pMuxSocket,pHashEntry); #else m_psocketgroupUsersWrite->add(*pMuxSocket); #endif } else if(pMixPacket->flags==CHANNEL_CLOSE) // closing one mix-channel (not the JAP<->mix connection!) { fmChannelListEntry* pEntry; pEntry=m_pChannelList->get(pMuxSocket,pMixPacket->channel); if(pEntry!=NULL) { pMixPacket->channel=pEntry->channelOut; getRandom(pMixPacket->data,DATA_SIZE); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif m_pQueueSendToMix->add(pQueueEntry, sizeof(tQueueEntry)); /* Don't delay upstream #ifdef DELAY_USERS m_pChannelList->decDelayBuckets(pHashEntry->delayBucketID); #endif*/ #ifdef LOG_CHANNEL //pEntry->packetsInFromUser++; getcurrentTimeMicros(current_time); diff_time=diff64(current_time,pEntry->timeCreated); CAMsg::printMsg(LOG_DEBUG,"1:%u,%Lu,%Lu,%u,%u,%u\n", pEntry->channelIn,pEntry->pHead->id,pEntry->timeCreated,pEntry->packetsInFromUser,pEntry->packetsOutToUser, diff_time); #endif delete pEntry->pCipher; // forget the symetric key of this connection pEntry->pCipher = NULL; m_pChannelList->removeChannel(pMuxSocket,pEntry->channelIn); } #ifdef _DEBUG else { // CAMsg::printMsg(LOG_DEBUG,"Invalid ID to close from Browser!\n"); } #endif } else // finally! a normal mix packet { CASymCipher* pCipher=NULL; fmChannelListEntry* pEntry; pEntry=m_pChannelList->get(pMuxSocket,pMixPacket->channel); if(pEntry!=NULL&&pMixPacket->flags==CHANNEL_DATA) { pMixPacket->channel=pEntry->channelOut; pCipher=pEntry->pCipher; pCipher->crypt1(pMixPacket->data,pMixPacket->data,DATA_SIZE); // queue the packet for sending to the next mix. #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif m_pQueueSendToMix->add(pQueueEntry, sizeof(tQueueEntry)); /* Don't delay upstream #ifdef DELAY_USERS m_pChannelList->decDelayBuckets(pHashEntry->delayBucketID); #endif*/ incMixedPackets(); #ifdef LOG_CHANNEL pEntry->packetsInFromUser++; #endif } else if(pEntry==NULL&&pMixPacket->flags==CHANNEL_OPEN) // open a new mix channel { // stefan: muesste das nicht vor die behandlung von CHANNEL_DATA? oder gilt OPEN => !DATA ? //es gilt: open -> data pHashEntry->pSymCipher->crypt1(pMixPacket->data,rsaBuff,KEY_SIZE); #ifdef REPLAY_DETECTION // replace time(NULL) with the real timestamp () // packet-timestamp*REPLAY_BASE + m_u64ReferenceTime if(m_pReplayDB->insert(rsaBuff,time(NULL))!=E_SUCCESS) { CAMsg::printMsg(LOG_INFO,"Replay: Duplicate packet ignored.\n"); continue; } #endif pCipher= new CASymCipher(); pCipher->setKey(rsaBuff); for(int i=0;i<16;i++) rsaBuff[i]=0xFF; pCipher->setIV2(rsaBuff); pCipher->crypt1(pMixPacket->data+KEY_SIZE,pMixPacket->data,DATA_SIZE-KEY_SIZE); getRandom(pMixPacket->data+DATA_SIZE-KEY_SIZE,KEY_SIZE); #if defined (LOG_CHANNEL) ||defined(DATA_RETENTION_LOG) HCHANNEL tmpC=pMixPacket->channel; #endif if(m_pChannelList->addChannel(pMuxSocket,pMixPacket->channel,pCipher,&pMixPacket->channel)!=E_SUCCESS) { //todo move up ? delete pCipher; pCipher = NULL; } else { #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif #ifdef LOG_CHANNEL fmChannelListEntry* pTmpEntry=m_pChannelList->get(pMuxSocket,tmpC); pTmpEntry->packetsInFromUser++; set64(pTmpEntry->timeCreated,pQueueEntry->timestamp_proccessing_start); #endif #ifdef DATA_RETENTION_LOG pQueueEntry->dataRetentionLogEntry.entity.first.channelid=pMixPacket->channel; pQueueEntry->dataRetentionLogEntry.t_in=time(NULL); //fmChannelListEntry* pTmpEntry1=m_pChannelList->get(pMuxSocket,tmpC); //memcpy(pQueueEntry->dataRetentionLogEntry.entity.first.ip_in,pTmpEntry1->pHead->peerIP,4); //pQueueEntry->dataRetentionLogEntry.entity.first.port_in=pTmpEntry1->pHead->peerPort; #endif m_pQueueSendToMix->add(pQueueEntry, sizeof(tQueueEntry)); /* Don't delay upstream #ifdef DELAY_USERS m_pChannelList->decDelayBuckets(pHashEntry->delayBucketID); #endif*/ incMixedPackets(); #ifdef _DEBUG // CAMsg::printMsg(LOG_DEBUG,"Added out channel: %u\n",pMixPacket->channel); #endif } } } } /*#ifdef DELAY_USERS } #endif*/ #ifdef HAVE_EPOLL NEXT_USER: pHashEntry=(fmHashTableEntry*)m_psocketgroupUsersRead->getNextSignaledSocketData(); #else }//if is signaled NEXT_USER: pHashEntry=m_pChannelList->getNext(); #endif } } //Third step //Sending to next mix // Now in a separate Thread (see loopSendToMix()) //Step 4 //Stepa 4a Receiving form Mix to Queue now in separat Thread //Step 4b Proccesing MixPackets received from Mix //todo check for error!!! countRead=m_nUser+1; while(countRead>0&&m_pQueueReadFromMix->getSize()>=sizeof(tQueueEntry)) { bAktiv=true; countRead--; ret=sizeof(tQueueEntry); m_pQueueReadFromMix->get((UINT8*)pQueueEntry,(UINT32*)&ret); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_start_OP); #endif if(pMixPacket->flags==CHANNEL_CLOSE) //close event { #if defined(_DEBUG) && !defined(__MIX_TEST) // CAMsg::printMsg(LOG_DEBUG,"Closing Channel: %u ...\n",pMixPacket->channel); #endif fmChannelList* pEntry=m_pChannelList->get(pMixPacket->channel); if(pEntry!=NULL) { /* a hack to solve the SSL problem: * set channel of downstream packet to in channel after they are dequeued * from pEntry->pQueueSend so we can retrieve the channel entry to decrement * the per channel count of enqueued downstream bytes. */ #ifndef SSL_HACK pMixPacket->channel=pEntry->channelIn; #endif pEntry->pCipher->crypt2(pMixPacket->data,pMixPacket->data,DATA_SIZE); //getRandom(pMixPacket->data,DATA_SIZE); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif pEntry->pHead->pQueueSend->add(pQueueEntry, sizeof(tQueueEntry)); #ifdef LOG_TRAFFIC_PER_USER pEntry->pHead->trafficOut++; #endif #ifdef COUNTRY_STATS m_PacketsPerCountryOUT[pEntry->pHead->countryID].inc(); #endif #ifdef SSL_HACK /* a hack to solve the SSL problem: * per channel count of enqueued downstream bytes */ pEntry->downStreamBytes += sizeof(tQueueEntry); #endif #ifdef LOG_CHANNEL pEntry->packetsOutToUser++; getcurrentTimeMicros(current_time); diff_time=diff64(current_time,pEntry->timeCreated); CAMsg::printMsg(LOG_DEBUG,"2:%u,%Lu,%Lu,%u,%u,%u\n", pEntry->channelIn,pEntry->pHead->id,pEntry->timeCreated,pEntry->packetsInFromUser,pEntry->packetsOutToUser, diff_time); #endif #ifdef HAVE_EPOLL //m_psocketgroupUsersWrite->add(*pEntry->pHead->pMuxSocket,pEntry->pHead); #else m_psocketgroupUsersWrite->add(*pEntry->pHead->pMuxSocket); #endif #ifndef SSL_HACK delete pEntry->pCipher; // forget the symetric key of this connection pEntry->pCipher = NULL; m_pChannelList->removeChannel(pEntry->pHead->pMuxSocket, pEntry->channelIn); /* a hack to solve the SSL problem: * remove channel after the close packet is enqueued * from pEntry->pQueueSend */ #endif } else { CAMsg::printMsg(LOG_DEBUG, "CAFirstMixA: close channel -> client but channel does not exist.\n"); } } else {//flag !=close #if defined(_DEBUG) && !defined(__MIX_TEST) // CAMsg::printMsg(LOG_DEBUG,"Sending Data to Browser!\n"); #endif fmChannelList* pEntry=m_pChannelList->get(pMixPacket->channel); if(pEntry!=NULL) { #ifdef LOG_CRIME if((pMixPacket->flags&CHANNEL_SIG_CRIME)==CHANNEL_SIG_CRIME) { UINT32 id=(pMixPacket->flags>>8)&0x000000FF; int log=LOG_ENCRYPTED; if(!pglobalOptions->isEncryptedLogEnabled()) log=LOG_CRIT; CAMsg::printMsg(log,"Detecting crime activity - ID: %u -- In-IP is: %u.%u.%u.%u \n",id,pEntry->pHead->peerIP[0],pEntry->pHead->peerIP[1],pEntry->pHead->peerIP[2],pEntry->pHead->peerIP[3]); continue; } #endif /* a hack to solve the SSL problem: * same as CHANNEL_CLOSE packets */ #ifndef SSL_HACK pMixPacket->channel=pEntry->channelIn; #endif pEntry->pCipher->crypt2(pMixPacket->data,pMixPacket->data,DATA_SIZE); #ifdef LOG_PACKET_TIMES getcurrentTimeMicros(pQueueEntry->timestamp_proccessing_end_OP); #endif pEntry->pHead->pQueueSend->add(pQueueEntry, sizeof(tQueueEntry)); /*CAMsg::printMsg( LOG_INFO,"adding data packet to queue: %x, queue size: %u bytes\n", pEntry->pHead->pQueueSend, pEntry->pHead->pQueueSend->getSize());*/ #ifdef LOG_TRAFFIC_PER_USER pEntry->pHead->trafficOut++; #endif #ifdef COUNTRY_STATS m_PacketsPerCountryOUT[pEntry->pHead->countryID].inc(); #endif #ifdef LOG_CHANNEL pEntry->packetsOutToUser++; #endif #ifdef SSL_HACK /* a hack to solve the SSL problem: * per channel count of downstream packets in bytes */ pEntry->downStreamBytes += sizeof(tQueueEntry); #endif #ifdef HAVE_EPOLL /*int epret = m_psocketgroupUsersWrite->add(*pEntry->pHead->pMuxSocket,pEntry->pHead); if(epret == E_UNKNOWN) { epret=errno; CAMsg::printMsg(LOG_INFO,"epoll_add returns: %s (return value: %d) \n", strerror(epret), epret); }*/ #else m_psocketgroupUsersWrite->add(*pEntry->pHead->pMuxSocket); #endif #ifndef NO_PARKING // UINT32 uQueueSize=pEntry->pHead->pQueueSend->getSize(); // if(uQueueSize>200000) // CAMsg::printMsg(LOG_INFO,"User Send Queue size is now %u\n",uQueueSize); if( #ifndef SSL_HACK pEntry->pHead->pQueueSend->getSize() > MAX_USER_SEND_QUEUE #else /* a hack to solve the SSL problem: * only suspend channels with > MAX_DATA_PER_CHANNEL bytes */ pEntry->downStreamBytes > MAX_DATA_PER_CHANNEL #endif && !pEntry->bIsSuspended) { pMixPacket->channel = pEntry->channelOut; pMixPacket->flags = CHANNEL_SUSPEND; #ifdef _DEBUG CAMsg::printMsg(LOG_INFO,"Sending suspend for channel: %u\n",pMixPacket->channel); #endif #ifdef LOG_PACKET_TIMES setZero64(pQueueEntry->timestamp_proccessing_start); #endif m_pQueueSendToMix->add(pQueueEntry, sizeof(tQueueEntry)); pEntry->bIsSuspended=true; pEntry->pHead->cSuspend++; } #endif incMixedPackets(); } else { #ifdef _DEBUG if(pMixPacket->flags!=CHANNEL_DUMMY) { /* CAMsg::printMsg(LOG_DEBUG,"Error Sending Data to Browser -- " "Channel-Id %u not valid!\n",pMixPacket->channel );*/ #ifdef LOG_CHANNEL CAMsg::printMsg(LOG_INFO,"Packet late arrive for channel: %u\n",pMixPacket->channel); #endif } #endif } } } ////Step 5 ////Writing to users... bAktiv = sendToUsers(); if(!bAktiv) msSleep(100); } //ERR: CAMsg::printMsg(LOG_CRIT,"Seems that we are restarting now!!\n"); m_bRunLog=false; //clean(); delete pQueueEntry; pQueueEntry = NULL; delete []tmpBuff; tmpBuff = NULL; #ifdef _DEBUG pLogThread->join(); delete pLogThread; pLogThread = NULL; #endif CAMsg::printMsg(LOG_CRIT,"Main Loop exited!!\n"); #endif//NEW_MIX_TYPE return E_UNKNOWN; } #endif //ONLY_LOCAL_PROXY /* last part of the main loop: * return true if the loop when at least one packet was sent * or false otherwise. */ bool CAFirstMixA::sendToUsers() { SINT32 countRead = m_psocketgroupUsersWrite->select(/*true,*/0); tQueueEntry *packetToSend = NULL; //tQueueEntry is just another word for MIXPACKET SINT32 packetSize = sizeof(tQueueEntry); CAQueue *controlMessageUserQueue = NULL; CAQueue *dataMessageUserQueue = NULL; CAQueue *processedQueue = NULL; /* one the above queues that should be used for processing*/ UINT32 extractSize = 0; bool bAktiv = false; /* Cyclic polling: gets all open sockets that will not block when invoking send() * but will only send at most one packet. After that control is returned to loop() */ #ifdef HAVE_EPOLL fmHashTableEntry* pfmHashEntry= (fmHashTableEntry*) m_psocketgroupUsersWrite->getFirstSignaledSocketData(); while(pfmHashEntry != NULL) { #else fmHashTableEntry* pfmHashEntry=m_pChannelList->getFirst(); while( (countRead > 0) && (pfmHashEntry != NULL) ) { if(m_psocketgroupUsersWrite->isSignaled(*pfmHashEntry->pMuxSocket)) { countRead--; #endif /* loop turn init */ extractSize = 0; processedQueue = NULL; packetToSend = &(pfmHashEntry->oQueueEntry); controlMessageUserQueue = pfmHashEntry->pControlMessageQueue; dataMessageUserQueue = pfmHashEntry->pQueueSend; //Control messages have a higher priority. if(controlMessageUserQueue->getSize() > 0) { processedQueue = controlMessageUserQueue; pfmHashEntry->bCountPacket = false; } else if( (dataMessageUserQueue->getSize() > 0) #ifdef DELAY_USERS && m_pChannelList->hasDelayBuckets(pfmHashEntry->delayBucketID) #endif ) { processedQueue = dataMessageUserQueue; pfmHashEntry->bCountPacket = true; } if(processedQueue != NULL) { extractSize = packetSize; bAktiv=true; if(pfmHashEntry->uAlreadySendPacketSize == -1) { processedQueue->get((UINT8*) packetToSend, &extractSize); /* Hack for SSL BUG */ #ifdef SSL_HACK finishPacket(pfmHashEntry); #endif //SSL_HACK pfmHashEntry->pMuxSocket->prepareForSend(&(packetToSend->packet)); pfmHashEntry->uAlreadySendPacketSize = 0; } } if( (extractSize > 0) || (pfmHashEntry->uAlreadySendPacketSize > 0) ) { SINT32 len = (pfmHashEntry->uAlreadySendPacketSize > 0) ? (packetSize - pfmHashEntry->uAlreadySendPacketSize) : extractSize; UINT8* packetToSendOffset = ((UINT8*)packetToSend) + pfmHashEntry->uAlreadySendPacketSize; CASocket *clientSocket = (CASocket*)pfmHashEntry->pMuxSocket; SINT32 ret = clientSocket->send(packetToSendOffset, len); if(ret > 0) { SINT32 accounting = E_SUCCESS; pfmHashEntry->uAlreadySendPacketSize += ret; if(pfmHashEntry->uAlreadySendPacketSize == MIXPACKET_SIZE) { #ifdef DELAY_USERS if(processedQueue != controlMessageUserQueue) { m_pChannelList->decDelayBuckets(pfmHashEntry->delayBucketID); } #endif #ifdef LOG_PACKET_TIMES if(!isZero64(pfmHashEntry->oQueueEntry.timestamp_proccessing_start)) { getcurrentTimeMicros(pfmHashEntry->oQueueEntry.timestamp_proccessing_end); m_pLogPacketStats->addToTimeingStats(pfmHashEntry->oQueueEntry,CHANNEL_DATA,false); } #endif pfmHashEntry->uAlreadySendPacketSize=-1; /* count this packet for accounting */ accounting = accountTrafficDownstream(pfmHashEntry); } if(accounting == E_SUCCESS) { if( (pfmHashEntry->cSuspend > 0) && (dataMessageUserQueue->getSize() < USER_SEND_BUFFER_RESUME) ) { resumeAllUserChannels(pfmHashEntry); } } } } //todo error handling #ifdef HAVE_EPOLL pfmHashEntry=(fmHashTableEntry*)m_psocketgroupUsersWrite->getNextSignaledSocketData(); } #else }//if is socket signaled pfmHashEntry=m_pChannelList->getNext(); } #endif return bAktiv; } SINT32 CAFirstMixA::accountTrafficDownstream(fmHashTableEntry* pfmHashEntry) { #ifdef PAYMENT // count packet for payment SINT32 ret = CAAccountingInstance::handleJapPacket(pfmHashEntry, !(pfmHashEntry->bCountPacket), true); if (ret == CAAccountingInstance::HANDLE_PACKET_CONNECTION_OK) { // renew the timeout pfmHashEntry->bRecoverTimeout = true; m_pChannelList->pushTimeoutEntry(pfmHashEntry); } else if (ret == CAAccountingInstance::HANDLE_PACKET_HOLD_CONNECTION || ret == CAAccountingInstance::HANDLE_PACKET_PREPARE_FOR_CLOSING_CONNECTION ) { // the next timeout might be deadly for this connection... //NOTE: this will close no client connection. A "real" kickout will occur //ONLY IF the AccountingInfo flag AUTH_FATAL_ERROR is set AND one control message //packet is handled by this method. Theses conditions hold when using the method //returnPrepareKickout. pfmHashEntry->bRecoverTimeout = false; } else if (ret == CAAccountingInstance::HANDLE_PACKET_CLOSE_CONNECTION ) { CAMsg::printMsg(LOG_DEBUG, "CAFirstMixA: Closing JAP connection due to illegal payment status!\n", ret); closeConnection(pfmHashEntry); return ERR_INTERN_SOCKET_CLOSED; } #endif return E_SUCCESS; } void CAFirstMixA::resumeAllUserChannels(fmHashTableEntry *pfmHashEntry) { notifyAllUserChannels(pfmHashEntry, CHANNEL_RESUME); } void CAFirstMixA::notifyAllUserChannels(fmHashTableEntry *pfmHashEntry, UINT16 flags) { if(pfmHashEntry == NULL) return; fmChannelListEntry* pEntry = m_pChannelList->getFirstChannelForSocket(pfmHashEntry->pMuxSocket); MIXPACKET *notifyPacket = new MIXPACKET; memset(notifyPacket, 0, sizeof(MIXPACKET)); notifyPacket->flags = flags; while(pEntry != NULL) { if(pEntry->bIsSuspended) { notifyPacket->channel = pEntry->channelOut; #ifdef _DEBUG CAMsg::printMsg(LOG_INFO,"Sent flags %u for channel: %u\n", flags, notifyPacket->channel); #endif m_pQueueSendToMix->add(notifyPacket, sizeof(MIXPACKET)); pEntry->bIsSuspended = false; } pEntry=m_pChannelList->getNextChannel(pEntry); } pfmHashEntry->cSuspend=0; delete notifyPacket; } //@todo: not a reliable solution. Still have to find the bug that causes SSL connections to be resetted //while large downloads are performed by the same user (only occurs in cascades with more than two mixes) #ifdef SSL_HACK void CAFirstMixA::finishPacket(fmHashTableEntry *pfmHashEntry) { tQueueEntry *packetToSend = &(pfmHashEntry->oQueueEntry); fmChannelList* cListEntry=m_pChannelList->get(packetToSend->packet.channel); if(cListEntry != NULL) { packetToSend->packet.channel = cListEntry->channelIn; cListEntry->downStreamBytes -= sizeof(tQueueEntry); #ifdef DEBUG CAMsg::printMsg(LOG_DEBUG, "CAFirstMixA: channels of current packet, in: %u, out: %u, count: %u, flags: 0x%x\n", cListEntry->channelIn, cListEntry->channelOut, cListEntry->downStreamBytes, packetToSend->packet.flags); #endif if(packetToSend->packet.flags == CHANNEL_CLOSE) { delete cListEntry->pCipher; cListEntry->pCipher = NULL; m_pChannelList->removeChannel(pfmHashEntry->pMuxSocket, cListEntry->channelIn); } } } #endif //SSL_HACK anon-proxy-00.05.38+20081230/TypeA/Makefile.am0000644000175000017500000000037110012420077016764 0ustar daviddavid# # Autoconfiguration files for proxytest (a MiX proxy) # Konrad Rieck # AUTOMAKE_OPTIONS = foreign noinst_LIBRARIES = libmixa.a libmixa_a_SOURCES = CAFirstMixA.cpp CAFirstMixA.hpp CALastMixA.cpp CALastMixA.hpp includes = @INCLUDES@ anon-proxy-00.05.38+20081230/TypeA/CALastMixA.hpp0000644000175000017500000000331310466075045017344 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CALASTMIXA__ #define __CALASTMIXA__ #include "../CALastMix.hpp" #ifndef ONLY_LOCAL_PROXY class CALastMixA:public CALastMix { protected: SINT32 loop(); }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/TypeA/CAFirstMixA.hpp0000644000175000017500000000416211123430145017516 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CAFIRSTMIXA__ #define __CAFIRSTMIXA__ #ifndef ONLY_LOCAL_PROXY #include "../CAFirstMix.hpp" class CAFirstMixA:public CAFirstMix { public: virtual void shutDown(); protected: SINT32 loop(); SINT32 closeConnection(fmHashTableEntry* pHashEntry); private: bool sendToUsers(); SINT32 accountTrafficDownstream(fmHashTableEntry* pfmHashEntry); void resumeAllUserChannels(fmHashTableEntry* pfmHashEntry); void notifyAllUserChannels(fmHashTableEntry *pfmHashEntry, UINT16 flags); #ifdef SSL_HACK void finishPacket(fmHashTableEntry *pfmHashEntry); #endif }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/controlchannelids.h0000644000175000017500000000326610271167225017610 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #define ACCOUNT_CONTROL_CHANNEL_ID 2 //For the payment #define REPLAY_CONTROL_CHANNEL_ID 3 //for replay detection #define TEST_CONTROL_CHANNEL_ID 255 //the 'ech' test control channel anon-proxy-00.05.38+20081230/CAPriceInfo.cpp0000644000175000017500000000357511035407104016507 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #ifdef PAYMENT #include "CAPriceInfo.hpp" CAPriceInfo::CAPriceInfo(UINT8* strMixId, UINT8* strPriceCertHash, SINT32 a_postition) { m_pStrMixId = strMixId; m_pStrPriceCertHash = strPriceCertHash; m_postition = a_postition; } CAPriceInfo::~CAPriceInfo() { delete[] m_pStrMixId; m_pStrMixId = NULL; delete[] m_pStrPriceCertHash; m_pStrPriceCertHash = NULL; } #endif anon-proxy-00.05.38+20081230/CAConditionVariable.cpp0000644000175000017500000000306407340652664020237 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #include "CAConditionVariable.hpp" anon-proxy-00.05.38+20081230/doAutoReconf.sh0000755000175000017500000000073511126501056016645 0ustar daviddavid#!/bin/sh #Use this file if you have changed anything related to autoconf/automake #Please use only the newest version of autoconf/automake rm missing aclocal.m4 configure config.h.in autoreconf -i -f -v -W all cvs commit -m "Auto generate through doAutoReconf.sh" -f missing aclocal.m4 Makefile.in config.h.in configure popt/Makefile.in xml/Makefile.in trio/Makefile.in tre/Makefile.in TypeA/Makefile.in TypeB/Makefile.in cvs commit -m "Auto generate through doAutoReconf.sh" anon-proxy-00.05.38+20081230/CAInfoService.hpp0000644000175000017500000001237511116234502017050 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CAINFOSERVICE__ #define __CAINFOSERVICE__ #ifndef ONLY_LOCAL_PROXY #include "CASignature.hpp" #include "CAFirstMix.hpp" #include "CAThread.hpp" #include "CAMutex.hpp" #include "CACmdLnOptions.hpp" #include "CAXMLBI.hpp" #define NR_REQUEST_TYPES 2 #define REQUEST_TYPE_POST 0 #define REQUEST_TYPE_GET 1 #define NR_REQUEST_COMMANDS 7 #define REQUEST_COMMAND_CONFIGURE 0 #define REQUEST_COMMAND_HELO 1 #define REQUEST_COMMAND_MIXINFO 2 #define REQUEST_COMMAND_DYNACASCADE 3 #define REQUEST_COMMAND_CASCADE 4 #define REQUEST_COMMAND_STATUS 5 #define REQUEST_COMMAND_TNC_DATA 6 #define ATTRIBUTE_SERIAL "serial" #define LOCALE_DEFAULT LOCALE_EN #define LOCALE_EN "en" class CAInfoService { #ifdef PAYMENT SINT32 getPaymentInstance(const UINT8* a_pstrPIID,CAXMLBI** pXMLBI, CASocketAddrINet* a_socketAddress); #endif public: CAInfoService(); CAInfoService(CAMix* pMix); ~CAInfoService(); SINT32 sendMixHelo(SINT32 requestCommand=-1,const UINT8* param=NULL); //SINT32 sendMixInfo(const UINT8* pMixID); SINT32 sendCascadeHelo(); SINT32 sendStatus(bool bIncludeCerts); SINT32 start(); SINT32 stop(); SINT32 getLevel(SINT32* puser,SINT32* prisk,SINT32* ptraffic); SINT32 getMixedPackets(UINT64& ppackets); #ifdef PAYMENT SINT32 getPaymentInstance(const UINT8* a_pstrPIID,CAXMLBI** pXMLBI); #endif bool isRunning() { return m_bRun; } SINT32 setSignature(CASignature* pSignature, CACertificate* a_ownCert, CACertificate* a_opCert); // added by ronin bool isConfiguring() { return m_bConfiguring; } void setConfiguring(bool a_configuring) { m_bConfiguring = a_configuring; } void setSerial(UINT64 a_serial) { m_serial = a_serial; } UINT8* getStatusXMLAsString(bool bIncludeCerts,UINT32& len); #ifdef DYNAMIC_MIX /** LERNGRUPPE */ SINT32 dynamicCascadeConfiguration(); bool newCascadeAvailable(); #endif public: static const UINT64 MINUTE; static const UINT64 SEND_LOOP_SLEEP; static const UINT64 SEND_CASCADE_INFO_WAIT; static const UINT64 SEND_MIX_INFO_WAIT; static const UINT64 SEND_STATUS_INFO_WAIT; static const UINT32 SEND_INFO_TIMEOUT_MS; static const UINT32 REPEAT_ON_STATUS_SENT_ERROR; private: static THREAD_RETURN TCascadeHelo(void *p); static THREAD_RETURN TCascadeStatus(void *p); static THREAD_RETURN TMixHelo(void *p); static THREAD_RETURN InfoLoop(void *p); SINT32 sendHelo(UINT8* a_strXML, UINT32 a_len, THREAD_RETURN (*a_thread)(void *), UINT8* a_strThreadName, SINT32 requestCommand, const UINT8* param = NULL); UINT8* getCascadeHeloXMLAsString(UINT32& len); SINT32 sendCascadeHelo(const UINT8* xml,UINT32 len,const CASocketAddrINet* a_socketAddress) const; SINT32 sendStatus(const UINT8* strStatusXML,UINT32 len,const CASocketAddrINet* a_socketAddress) const; UINT8 **getOperatorTnCsAsStrings(UINT32 **lengths, XMLSize_t *nrOfTnCs); SINT32 sendOperatorTnCData(); UINT8 *getMixHeloXMLAsString(UINT32& len); UINT8 *xmlDocToStringWithSignature(DOMNode *a_node, UINT32& a_len, CACertStore* pIncludeCerts); SINT32 sendMixHelo(const UINT8* strMixHeloXML,UINT32 len,SINT32 requestCommand,const UINT8* param, const CASocketAddrINet* a_socketAddress); // added by ronin SINT32 handleConfigEvent(XERCES_CPP_NAMESPACE::DOMDocument* doc) const; struct InfoServiceHeloMsg; volatile bool m_bRun; CASignature* m_pSignature; CACertStore* m_pcertstoreOwnCerts; CAMix* m_pMix; CAThread* m_pthreadRunLoop; CAConditionVariable * m_pLoopCV; UINT64 m_lastMixedPackets; UINT64 m_serial; UINT32 m_minuts; SINT32 m_expectedMixRelPos; bool m_bConfiguring; #ifdef DYNAMIC_MIX bool m_bReconfig; #endif }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/popt/0000755000175000017500000000000011126517130014673 5ustar daviddavidanon-proxy-00.05.38+20081230/popt/popthelp.cpp0000644000175000017500000002011707417002341017234 0ustar daviddavid/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.redhat.com/pub/code/popt */ #include "../StdAfx.h" #include "poptint.h" static void displayArgs(poptContext con, /*@unused@*/ enum poptCallbackReason foo, struct poptOption * key, /*@unused@*/ const char * arg, /*@unused@*/ void * data) { if (key->shortName== '?') poptPrintHelp(con, stdout, 0); else poptPrintUsage(con, stdout, 0); exit(0); } struct poptOption poptHelpOptions[] = { { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, { NULL, '\0', 0, NULL, 0, NULL, NULL } } ; /*@observer@*/ /*@null@*/ static const char *const getTableTranslationDomain(const struct poptOption *table) { const struct poptOption *opt; for(opt = table; opt->longName || opt->shortName || opt->arg; opt++) { if(opt->argInfo == POPT_ARG_INTL_DOMAIN) return (const char* const)opt->arg; } return NULL; } /*@observer@*/ /*@null@*/ static const char *const getArgDescrip(const struct poptOption * opt, const char *translation_domain) { if (!(opt->argInfo & POPT_ARG_MASK)) return NULL; if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2)) if (opt->argDescrip) return POPT_(opt->argDescrip); if (opt->argDescrip) return D_(translation_domain, opt->argDescrip); return POPT_("ARG"); } static void singleOptionHelp(FILE * f, int maxLeftCol, const struct poptOption * opt, const char *translation_domain) { int indentLength = maxLeftCol + 5; int lineLength = 79 - indentLength; const char * help = D_(translation_domain, opt->descrip); int helpLength; const char * ch; char format[10]; char * left; const char * argDescrip = getArgDescrip(opt, translation_domain); left = (char*)malloc(maxLeftCol + 1); *left = '\0'; if (opt->longName && opt->shortName) sprintf(left, "-%c, --%s", opt->shortName, opt->longName); else if (opt->shortName) sprintf(left, "-%c", opt->shortName); else if (opt->longName) sprintf(left, "--%s", opt->longName); if (!*left) return ; if (argDescrip) { strcat(left, "="); strcat(left, argDescrip); } if (help) fprintf(f," %-*s ", maxLeftCol, left); else { fprintf(f," %s\n", left); goto out; } helpLength = strlen(help); while (helpLength > lineLength) { ch = help + lineLength - 1; while (ch > help && !isspace(*ch)) ch--; if (ch == help) break; /* give up */ while (ch > (help + 1) && isspace(*ch)) ch--; ch++; sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength); fprintf(f, format, help, " "); help = ch; while (isspace(*help) && *help) help++; helpLength = strlen(help); } if (helpLength) fprintf(f, "%s\n", help); out: free(left); } static int maxArgWidth(const struct poptOption * opt, const char * translation_domain) { int max = 0; int thiS; const char * s; while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { thiS = maxArgWidth((struct poptOption*)opt->arg, translation_domain); if (thiS > max) max = thiS; } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { thiS = opt->shortName ? 2 : 0; if (opt->longName) { if (thiS) thiS += 2; thiS += strlen(opt->longName) + 2; } s = getArgDescrip(opt, translation_domain); if (s) thiS += strlen(s) + 1; if (thiS > max) max = thiS; } opt++; } return max; } static void singleTableHelp(FILE * f, const struct poptOption * table, int left, const char *translation_domain) { const struct poptOption * opt; const char *sub_transdom; opt = table; while (opt->longName || opt->shortName || opt->arg) { if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) singleOptionHelp(f, left, opt, translation_domain); opt++; } opt = table; while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { sub_transdom = getTableTranslationDomain((struct poptOption*)opt->arg); if(!sub_transdom) sub_transdom = translation_domain; if (opt->descrip) fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip)); singleTableHelp(f, (struct poptOption*)opt->arg, left, sub_transdom); } opt++; } } static int showHelpIntro(poptContext con, FILE * f) { int len = 6; const char * fn; fprintf(f, POPT_("Usage:")); if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { fn = con->optionStack->argv[0]; if (strchr(fn, '/')) fn = strchr(fn, '/') + 1; fprintf(f, " %s", fn); len += strlen(fn) + 1; } return len; } void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) { int leftColWidth; showHelpIntro(con, f); if (con->otherHelp) fprintf(f, " %s\n", con->otherHelp); else fprintf(f, " %s\n", POPT_("[OPTION...]")); leftColWidth = maxArgWidth(con->options, NULL); singleTableHelp(f, con->options, leftColWidth, NULL); } static int singleOptionUsage(FILE * f, int cursor, const struct poptOption * opt, const char *translation_domain) { int len = 3; char shortStr[2] = { '\0', '\0' }; const char * item = shortStr; const char * argDescrip = getArgDescrip(opt, translation_domain); if (opt->shortName) { if (!(opt->argInfo & POPT_ARG_MASK)) return cursor; /* we did these already */ len++; *shortStr = opt->shortName; shortStr[1] = '\0'; } else if (opt->longName) { len += 1 + strlen(opt->longName); item = opt->longName; } if (len == 3) return cursor; if (argDescrip) len += strlen(argDescrip) + 1; if ((cursor + len) > 79) { fprintf(f, "\n "); cursor = 7; } fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item, argDescrip ? (opt->shortName ? " " : "=") : "", argDescrip ? argDescrip : ""); return cursor + len + 1; } static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table, const char *translation_domain) { const struct poptOption * opt; opt = table; while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) translation_domain = (const char *)opt->arg; else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) cursor = singleTableUsage(f, cursor, (struct poptOption*)opt->arg, translation_domain); else if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) cursor = singleOptionUsage(f, cursor, opt, translation_domain); opt++; } return cursor; } static int showShortOptions(const struct poptOption * opt, FILE * f, char * str) { char s[300]; /* this is larger then the ascii set, so it should do just fine */ s[0] = '\0'; if (str == NULL) { memset(s, 0, sizeof(s)); str = s; } while (opt->longName || opt->shortName || opt->arg) { if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK)) str[strlen(str)] = opt->shortName; else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) showShortOptions((struct poptOption*)opt->arg, f, str); opt++; } if (s != str || !*s) return 0; fprintf(f, " [-%s]", s); return strlen(s) + 4; } void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) { int cursor; cursor = showHelpIntro(con, f); cursor += showShortOptions(con->options, f, NULL); singleTableUsage(f, cursor, con->options, NULL); if (con->otherHelp) { cursor += strlen(con->otherHelp) + 1; if (cursor > 79) fprintf(f, "\n "); fprintf(f, " %s", con->otherHelp); } fprintf(f, "\n"); } void poptSetOtherOptionHelp(poptContext con, const char * text) { if (con->otherHelp) xfree(con->otherHelp); con->otherHelp = xstrdup(text); } anon-proxy-00.05.38+20081230/popt/Makefile.in0000644000175000017500000003076611126501037016753 0ustar daviddavid# Makefile.in generated by automake 1.10.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Autoconfiguration files for proxytest (a MiX proxy) # Konrad Rieck # VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = popt DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libpopt_a_AR = $(AR) $(ARFLAGS) libpopt_a_LIBADD = am_libpopt_a_OBJECTS = popt.$(OBJEXT) poptparse.$(OBJEXT) \ popthelp.$(OBJEXT) libpopt_a_OBJECTS = $(am_libpopt_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libpopt_a_SOURCES) DIST_SOURCES = $(libpopt_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBCPPUNIT = @LIBCPPUNIT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign noinst_LIBRARIES = libpopt.a libpopt_a_SOURCES = popt.cpp poptparse.cpp popthelp.cpp \ popt.h poptint.h system.h includes = @INCLUDES@ all: all-am .SUFFIXES: .SUFFIXES: .cpp .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign popt/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign popt/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libpopt.a: $(libpopt_a_OBJECTS) $(libpopt_a_DEPENDENCIES) -rm -f libpopt.a $(libpopt_a_AR) libpopt.a $(libpopt_a_OBJECTS) $(libpopt_a_LIBADD) $(RANLIB) libpopt.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popthelp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poptparse.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-exec-am: install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: anon-proxy-00.05.38+20081230/popt/popt.h0000644000175000017500000001244107416774347016056 0ustar daviddavid/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.redhat.com/pub/code/popt */ #ifndef H_POPT #define H_POPT /*#ifdef __cplusplus extern "C" { #endif */ #include /* for FILE * */ #define POPT_OPTION_DEPTH 10 #define POPT_ARG_NONE 0 #define POPT_ARG_STRING 1 #define POPT_ARG_INT 2 #define POPT_ARG_LONG 3 #define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */ #define POPT_ARG_CALLBACK 5 /* table-wide callback... must be set first in table; arg points to callback, descrip points to callback data to pass */ #define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain for this table and any included tables; arg points to the domain string */ #define POPT_ARG_VAL 7 /* arg should take value val */ #define POPT_ARG_MASK 0x0000FFFF #define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */ #define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */ #define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */ #define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */ #define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */ #define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line, not the subtable */ #define POPT_ERROR_NOARG -10 #define POPT_ERROR_BADOPT -11 #define POPT_ERROR_OPTSTOODEEP -13 #define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ #define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ #define POPT_ERROR_BADNUMBER -17 #define POPT_ERROR_OVERFLOW -18 /* poptBadOption() flags */ #define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */ /* poptGetContext() flags */ #define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */ #define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */ #define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */ struct poptOption { /*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */ char shortName; /* may be '\0' */ int argInfo; /*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */ int val; /* 0 means don't return, just update flag */ /*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */ /*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */ }; struct poptAlias { /*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */ char shortName; /* may be '\0' */ int argc; /*@owned@*/ const char ** argv; /* must be free()able */ }; extern struct poptOption poptHelpOptions[]; #define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \ 0, "Help options", NULL }, typedef struct poptContext_s * poptContext; #ifndef __cplusplus typedef struct poptOption * poptOption; #endif enum poptCallbackReason { POPT_CALLBACK_REASON_PRE, POPT_CALLBACK_REASON_POST, POPT_CALLBACK_REASON_OPTION }; typedef void (*poptCallbackType)(poptContext con, enum poptCallbackReason reason, const struct poptOption * opt, const char * arg, const void * data); /*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name, int argc, /*@keep@*/ const char ** argv, /*@keep@*/ const struct poptOption * options, int flags); void poptResetContext(poptContext con); /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ int poptGetNextOpt(poptContext con); /* returns NULL if no argument is available */ /*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con); /* returns NULL if no more options are available */ /*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con); /*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con); /*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con); /* returns the option which caused the most recent error */ /*@observer@*/ const char * poptBadOption(poptContext con, int flags); void poptFreeContext( /*@only@*/ poptContext con); int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv); int poptAddAlias(poptContext con, struct poptAlias alias, int flags); int poptReadConfigFile(poptContext con, const char * fn); /* like above, but reads /etc/popt and $HOME/.popt along with environment vars */ int poptReadDefaultConfig(poptContext con, int useEnv); /* argv should be freed -- this allows ', ", and \ quoting, but ' is treated the same as " and both may include \ quotes */ int poptDupArgv(int argc, const char **argv, /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); int poptParseArgvString(const char * s, /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr); /*@observer@*/ const char * /*const*/ poptStrerror(const int error); void poptSetExecPath(poptContext con, const char * path, int allowAbsolute); void poptPrintHelp(poptContext con, FILE * f, int flags); void poptPrintUsage(poptContext con, FILE * f, int flags); void poptSetOtherOptionHelp(poptContext con, const char * text); /*@observer@*/ const char * poptGetInvocationName(poptContext con); /* shuffles argv pointers to remove stripped args, returns new argc */ int poptStrippedArgv(poptContext con, int argc, char **argv); /* #ifdef __cplusplus } #endif */ #endif anon-proxy-00.05.38+20081230/popt/poptparse.cpp0000644000175000017500000000422507417002341017420 0ustar daviddavid/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.redhat.com/pub/code/popt */ #include "../StdAfx.h" //#include "system.h" //#include "popt.h" #define POPT_ARGV_ARRAY_GROW_DELTA 5 int poptDupArgv(int argc, const char **argv, int * argcPtr, const char *** argvPtr) { size_t nb = (argc + 1) * sizeof(*argv); const char ** argv2; char * dst; int i; for (i = 0; i < argc; i++) { if (argv[i] == NULL) return POPT_ERROR_NOARG; nb += strlen(argv[i]) + 1; } dst = (char *)malloc(nb); argv2 = (const char**) dst; dst += (argc + 1) * sizeof(*argv); for (i = 0; i < argc; i++) { argv2[i] = dst; dst += strlen(strcpy(dst, argv[i])) + 1; } argv2[argc] = NULL; *argvPtr = argv2; *argcPtr = argc; return 0; } int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) { const char * src; char quote = '\0'; int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; const char ** argv = (const char **)malloc(sizeof(*argv) * argvAlloced); int argc = 0; int buflen = strlen(s) + 1; char * buf = (char*)memset(alloca(buflen), 0, buflen); argv[argc] = buf; for (src = s; *src; src++) { if (quote == *src) { quote = '\0'; } else if (quote) { if (*src == '\\') { src++; if (!*src) { free((void*)argv); return POPT_ERROR_BADQUOTE; } if (*src != quote) *buf++ = '\\'; } *buf++ = *src; } else if (isspace(*src)) { if (*argv[argc]) { buf++, argc++; if (argc == argvAlloced) { argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; argv = (const char**)realloc((void*)argv, sizeof(*argv) * argvAlloced); } argv[argc] = buf; } } else switch (*src) { case '"': case '\'': quote = *src; break; case '\\': src++; if (!*src) { free((void*)argv); return POPT_ERROR_BADQUOTE; } /*@fallthrough@*/ default: *buf++ = *src; break; } } if (strlen(argv[argc])) { argc++, buf++; } (void) poptDupArgv(argc, argv, argcPtr, argvPtr); free((void*)argv); return 0; } anon-proxy-00.05.38+20081230/popt/Makefile.old0000644000175000017500000000060111122436455017113 0ustar daviddavidlibpopt.a: popt.cpp poptparse.cpp popthelp.cpp $(CC) -c $(CPPFLAGS) $(INCLUDE) $(DEBUG) -DHAVE_STRERROR popt.cpp -o popt.o $(CC) -c $(CPPFLAGS) $(INCLUDE) $(DEBUG) -DHAVE_STRERROR poptparse.cpp -o poptparse.o $(CC) -c $(CPPFLAGS) $(INCLUDE) $(DEBUG) -DHAVE_STRERROR popthelp.cpp -o popthelp.o ar -rcs libpopt.a popt.o poptparse.o popthelp.o clean: rm -f *.o rm -f libpopt.a anon-proxy-00.05.38+20081230/popt/Makefile.am0000644000175000017500000000040107417001607016727 0ustar daviddavid# # Autoconfiguration files for proxytest (a MiX proxy) # Konrad Rieck # AUTOMAKE_OPTIONS = foreign noinst_LIBRARIES = libpopt.a libpopt_a_SOURCES = popt.cpp poptparse.cpp popthelp.cpp \ popt.h poptint.h system.h includes = @INCLUDES@ anon-proxy-00.05.38+20081230/popt/system.h0000644000175000017500000000206510012415162016366 0ustar daviddavid#ifdef __NeXT /* access macros are not declared in non posix mode in unistd.h - don't try to use posix on NeXTstep 3.3 ! */ #include #endif #ifdef __ICC #define HAVE_ALLOCA_H //#define alloca(size) _alloca(size) #else /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ #ifdef HAVE_ALLOCA_H #include #else #ifdef _AIX #pragma alloca #else #ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); #endif #endif #endif #elif defined(__GNUC__) && defined(__STRICT_ANSI__) #define alloca __builtin_alloca #else #ifdef HAVE_ALLOCA_H #include #endif #endif #ifdef _WIN32 #define alloca _alloca #endif #endif /*@only@*/ char * xstrdup (const char *str); #if HAVE_MCHECK_H && defined(__GNUC__) #define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) #define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str))) #else #define xstrdup(_str) strdup(_str) #endif /* HAVE_MCHECK_H && defined(__GNUC__) */ anon-proxy-00.05.38+20081230/popt/popt.cpp0000644000175000017500000004746307417002341016400 0ustar daviddavid/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.redhat.com/pub/code/popt */ #include "../StdAfx.h" //#include "system.h" //#include "popt.h" #include "poptint.h" #ifdef _WIN32 #define HAVE_STRERROR #endif #ifndef HAVE_STRERROR static char * strerror(int errno) { extern int sys_nerr; extern char * sys_errlist[]; if ((0 <= errno) && (errno < sys_nerr)) return sys_errlist[errno]; else return POPT_("unknown errno"); } #endif void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) { if (con->execPath) xfree(con->execPath); con->execPath = xstrdup(path); con->execAbsolute = allowAbsolute; } static void invokeCallbacks(poptContext con, const struct poptOption * table, int post) { const struct poptOption * opt = table; poptCallbackType cb; while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { invokeCallbacks(con,(struct poptOption*) opt->arg, post); } else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) && ((!post && (opt->argInfo & POPT_CBFLAG_PRE)) || ( post && (opt->argInfo & POPT_CBFLAG_POST)))) { cb = (poptCallbackType)opt->arg; cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); } opt++; } } poptContext poptGetContext(const char * name, int argc, const char ** argv, const struct poptOption * options, int flags) { poptContext con = (poptContext)malloc(sizeof(*con)); memset(con, 0, sizeof(*con)); con->os = con->optionStack; con->os->argc = argc; con->os->argv = argv; con->os->argb = NULL; if (!(flags & POPT_CONTEXT_KEEP_FIRST)) con->os->next = 1; /* skip argv[0] */ con->leftovers = (const char**)calloc( (argc + 1), sizeof(char *) ); con->options = options; con->aliases = NULL; con->numAliases = 0; con->flags = flags; con->execs = NULL; con->numExecs = 0; con->finalArgvAlloced = argc * 2; con->finalArgv = (const char**)calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) ); con->execAbsolute = 1; con->arg_strip = NULL; if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) con->flags |= POPT_CONTEXT_POSIXMEHARDER; if (name) con->appName = strcpy((char*)malloc(strlen(name) + 1), name); invokeCallbacks(con, con->options, 0); return con; } static void cleanOSE(struct optionStackEntry *os) { if (os->nextArg) { xfree(os->nextArg); os->nextArg = NULL; } if (os->argv) { xfree(os->argv); os->argv = NULL; } if (os->argb) { PBM_FREE(os->argb); os->argb = NULL; } } void poptResetContext(poptContext con) { int i; while (con->os > con->optionStack) { cleanOSE(con->os--); } if (con->os->argb) { PBM_FREE(con->os->argb); con->os->argb = NULL; } con->os->currAlias = NULL; con->os->nextCharArg = NULL; con->os->nextArg = NULL; con->os->next = 1; /* skip argv[0] */ con->numLeftovers = 0; con->nextLeftover = 0; con->restLeftover = 0; con->doExec = NULL; for (i = 0; i < con->finalArgvCount; i++) { if (con->finalArgv[i]) { xfree(con->finalArgv[i]); con->finalArgv[i] = NULL; } } con->finalArgvCount = 0; if (con->arg_strip) { PBM_FREE(con->arg_strip); con->arg_strip = NULL; } } /* Only one of longName, shortName may be set at a time */ static int handleExec(poptContext con, char * longName, char shortName) { int i; i = con->numExecs - 1; if (longName) { while (i >= 0 && (!con->execs[i].longName || strcmp(con->execs[i].longName, longName))) i--; } else { while (i >= 0 && con->execs[i].shortName != shortName) i--; } if (i < 0) return 0; if (con->flags & POPT_CONTEXT_NO_EXEC) return 1; if (con->doExec == NULL) { con->doExec = con->execs + i; return 1; } /* We already have an exec to do; remember this option for next time 'round */ if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { con->finalArgvAlloced += 10; con->finalArgv = (const char**)realloc((void*)con->finalArgv, sizeof(*con->finalArgv) * con->finalArgvAlloced); } i = con->finalArgvCount++; { char *s =(char*) malloc((longName ? strlen(longName) : 0) + 3); if (longName) sprintf(s, "--%s", longName); else sprintf(s, "-%c", shortName); con->finalArgv[i] = s; } return 1; } /* Only one of longName, shortName may be set at a time */ static int handleAlias(poptContext con, const char * longName, char shortName, /*@keep@*/ const char * nextCharArg) { int i; if (con->os->currAlias && con->os->currAlias->longName && longName && !strcmp(con->os->currAlias->longName, longName)) return 0; if (con->os->currAlias && shortName && shortName == con->os->currAlias->shortName) return 0; i = con->numAliases - 1; if (longName) { while (i >= 0 && (!con->aliases[i].longName || strcmp(con->aliases[i].longName, longName))) i--; } else { while (i >= 0 && con->aliases[i].shortName != shortName) i--; } if (i < 0) return 0; if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; if (nextCharArg && *nextCharArg) con->os->nextCharArg = nextCharArg; con->os++; con->os->next = 0; con->os->stuffed = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = con->aliases + i; poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; return 1; } /* static void execCommand(poptContext con) { const char ** argv; int pos = 0; const char * script = con->doExec->script; argv = malloc(sizeof(*argv) * (6 + con->numLeftovers + con->finalArgvCount)); if (!con->execAbsolute && strchr(script, '/')) return; if (!strchr(script, '/') && con->execPath) { char *s = alloca(strlen(con->execPath) + strlen(script) + 2); sprintf(s, "%s/%s", con->execPath, script); argv[pos] = s; } else { argv[pos] = script; } pos++; argv[pos] = findProgramPath(con->os->argv[0]); if (argv[pos]) pos++; argv[pos++] = ";"; memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount); pos += con->finalArgvCount; if (con->numLeftovers) { argv[pos++] = "--"; memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers); pos += con->numLeftovers; } argv[pos++] = NULL; #ifdef __hpux setresuid(getuid(), getuid(),-1); #else // // XXX " ... on BSD systems setuid() should be preferred over setreuid()" // XXX sez' Timur Bakeyev // XXX from Norbert Warmuth // #if defined(HAVE_SETUID) setuid(getuid()); #elif defined (HAVE_SETREUID) setreuid(getuid(), getuid()); //hlauer: not portable to hpux9.01 #else ; // Can't drop privileges #endif #endif execvp(argv[0], (char *const *)argv); } */ /*@observer@*/ static const struct poptOption * findOption(const struct poptOption * table, const char * longName, char shortName, /*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData, int singleDash) { const struct poptOption * opt = table; const struct poptOption * opt2; const struct poptOption * cb = NULL; /* This happens when a single - is given */ if (singleDash && !shortName && !*longName) shortName = '-'; while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { opt2 = findOption((struct poptOption*)opt->arg, longName, shortName, callback, callbackData, singleDash); if (opt2) { if (*callback && !*callbackData) *callbackData = opt->descrip; return opt2; } } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) { cb = opt; } else if (longName && opt->longName && (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && !strcmp(longName, opt->longName)) { break; } else if (shortName && shortName == opt->shortName) { break; } opt++; } if (!opt->longName && !opt->shortName) return NULL; *callbackData = NULL; *callback = NULL; if (cb) { *callback = (poptCallbackType)cb->arg; if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) *callbackData = cb->descrip; } return opt; } static const char *findNextArg(poptContext con, unsigned argx, int deletE) { struct optionStackEntry * os = con->os; const char * arg; do { int i; arg = NULL; while (os->next == os->argc && os > con->optionStack) os--; if (os->next == os->argc && os == con->optionStack) break; for (i = os->next; i < os->argc; i++) { if (os->argb && PBM_ISSET(i, os->argb)) continue; if (*os->argv[i] == '-') continue; if (--argx > 0) continue; arg = os->argv[i]; if (deletE) { if (os->argb == NULL) os->argb = (pbm_set*)PBM_ALLOC(os->argc); PBM_SET(i, os->argb); } break; } if (os > con->optionStack) os--; } while (arg == NULL); return arg; } static /*@only@*/ const char * expandNextArg(poptContext con, const char * s) { const char *a; size_t alen; char *t, *te; size_t tn = strlen(s) + 1; char c; te = t = (char*)malloc(tn);; while ((c = *s++) != '\0') { switch (c) { #if 0 /* XXX can't do this */ case '\\': /* escape */ c = *s++; break; #endif case '!': if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) break; if ((a = findNextArg(con, 1, 1)) == NULL) break; s += 3; alen = strlen(a); tn += alen; *te = '\0'; t = (char*)realloc(t, tn); te = t + strlen(t); strncpy(te, a, alen); te += alen; continue; /*@notreached@*/ break; default: break; } *te++ = c; } *te = '\0'; t = (char*)realloc(t, strlen(t)+1); /* XXX memory leak, hard to plug */ return t; } static void poptStripArg(poptContext con, int which) { if(con->arg_strip == NULL) { con->arg_strip = (pbm_set*)PBM_ALLOC(con->optionStack[0].argc); } PBM_SET(which, con->arg_strip); } /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ int poptGetNextOpt(poptContext con) { const struct poptOption * opt = NULL; int done = 0; while (!done) { const char * origOptString = NULL; poptCallbackType cb = NULL; const void * cbData = NULL; const char * longArg = NULL; int canstrip = 0; while (!con->os->nextCharArg && con->os->next == con->os->argc && con->os > con->optionStack) { cleanOSE(con->os--); } if (!con->os->nextCharArg && con->os->next == con->os->argc) { invokeCallbacks(con, con->options, 1); //if (con->doExec) execCommand(con); return -1; } /* Process next long option */ if (!con->os->nextCharArg) { char * localOptString, * optString; int thisopt; if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) { con->os->next++; continue; } thisopt=con->os->next; origOptString = con->os->argv[con->os->next++]; if (con->restLeftover || *origOptString != '-') { con->leftovers[con->numLeftovers++] = origOptString; if (con->flags & POPT_CONTEXT_POSIXMEHARDER) con->restLeftover = 1; continue; } /* Make a copy we can hack at */ localOptString = optString = strcpy((char*)alloca(strlen(origOptString) + 1), origOptString); if (!optString[0]) return POPT_ERROR_BADOPT; if (optString[1] == '-' && !optString[2]) { con->restLeftover = 1; continue; } else { char *oe; int singleDash; optString++; if (*optString == '-') singleDash = 0, optString++; else singleDash = 1; /* XXX aliases with arg substitution need "--alias=arg" */ if (handleAlias(con, optString, '\0', NULL)) continue; if (handleExec(con, optString, '\0')) continue; /* Check for "--long=arg" option. */ for (oe = optString; *oe && *oe != '='; oe++) ; if (*oe == '=') { *oe++ = '\0'; /* XXX longArg is mapped back to persistent storage. */ longArg = origOptString + (oe - localOptString); } opt = findOption(con->options, optString, '\0', &cb, &cbData, singleDash); if (!opt && !singleDash) return POPT_ERROR_BADOPT; } if (!opt) { con->os->nextCharArg = origOptString + 1; } else { if(con->os == con->optionStack && opt->argInfo & POPT_ARGFLAG_STRIP) { canstrip = 1; poptStripArg(con, thisopt); } } } /* Process next short option */ if (con->os->nextCharArg) { origOptString = con->os->nextCharArg; con->os->nextCharArg = NULL; if (handleAlias(con, NULL, *origOptString, origOptString + 1)) { origOptString++; continue; } if (handleExec(con, NULL, *origOptString)) continue; opt = findOption(con->options, NULL, *origOptString, &cb, &cbData, 0); if (!opt) return POPT_ERROR_BADOPT; origOptString++; if (*origOptString) con->os->nextCharArg = origOptString; } if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) { *((int *)opt->arg) = 1; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) { if (opt->arg) *((int *) opt->arg) = opt->val; } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { if (con->os->nextArg) { xfree(con->os->nextArg); con->os->nextArg = NULL; } if (longArg) { con->os->nextArg = expandNextArg(con, longArg); } else if (con->os->nextCharArg) { con->os->nextArg = expandNextArg(con, con->os->nextCharArg); con->os->nextCharArg = NULL; } else { while (con->os->next == con->os->argc && con->os > con->optionStack) { cleanOSE(con->os--); } if (con->os->next == con->os->argc) return POPT_ERROR_NOARG; /* make sure this isn't part of a short arg or the result of an alias expansion */ if(con->os == con->optionStack && opt->argInfo & POPT_ARGFLAG_STRIP && canstrip) { poptStripArg(con, con->os->next); } con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]); } if (opt->arg) { long aLong; char *end; switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_STRING: /* XXX memory leak, hard to plug */ *((const char **) opt->arg) = xstrdup(con->os->nextArg); break; case POPT_ARG_INT: case POPT_ARG_LONG: aLong = strtol(con->os->nextArg, &end, 0); if (!(end && *end == '\0')) return POPT_ERROR_BADNUMBER; if (aLong == LONG_MIN || aLong == LONG_MAX) return POPT_ERROR_OVERFLOW; if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { *((long *) opt->arg) = aLong; } else { if (aLong > INT_MAX || aLong < INT_MIN) return POPT_ERROR_OVERFLOW; *((int *) opt->arg) = aLong; } break; default: fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"), opt->argInfo & POPT_ARG_MASK); exit(EXIT_FAILURE); } } } if (cb) cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData); else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)) done = 1; if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { con->finalArgvAlloced += 10; con->finalArgv = (const char**)realloc((void*)con->finalArgv, sizeof(*con->finalArgv) * con->finalArgvAlloced); } { char *s = (char*)malloc((opt->longName ? strlen(opt->longName) : 0) + 3); if (opt->longName) sprintf(s, "--%s", opt->longName); else sprintf(s, "-%c", opt->shortName); con->finalArgv[con->finalArgvCount++] = s; } if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL) { con->finalArgv[con->finalArgvCount++] = xstrdup(con->os->nextArg); } } return opt->val; } const char * poptGetOptArg(poptContext con) { const char * ret = con->os->nextArg; con->os->nextArg = NULL; return ret; } const char * poptGetArg(poptContext con) { if (con->numLeftovers == con->nextLeftover) return NULL; return con->leftovers[con->nextLeftover++]; } const char * poptPeekArg(poptContext con) { if (con->numLeftovers == con->nextLeftover) return NULL; return con->leftovers[con->nextLeftover]; } const char ** poptGetArgs(poptContext con) { if (con->numLeftovers == con->nextLeftover) return NULL; /* some apps like [like RPM ;-) ] need this NULL terminated */ con->leftovers[con->numLeftovers] = NULL; return (con->leftovers + con->nextLeftover); } void poptFreeContext(poptContext con) { int i; poptResetContext(con); if (con->os->argb) free(con->os->argb); for (i = 0; i < con->numAliases; i++) { if (con->aliases[i].longName) xfree(con->aliases[i].longName); free((void*)con->aliases[i].argv); } for (i = 0; i < con->numExecs; i++) { if (con->execs[i].longName) xfree(con->execs[i].longName); xfree(con->execs[i].script); } if (con->execs) xfree(con->execs); free((void*)con->leftovers); free((void*)con->finalArgv); if (con->appName) xfree(con->appName); if (con->aliases) free(con->aliases); if (con->otherHelp) xfree(con->otherHelp); if (con->execPath) xfree(con->execPath); if (con->arg_strip) PBM_FREE(con->arg_strip); free(con); } int poptAddAlias(poptContext con, struct poptAlias newAlias, /*@unused@*/ int flags) { int aliasNum = con->numAliases++; struct poptAlias * alias; /* SunOS won't realloc(NULL, ...) */ if (!con->aliases) con->aliases = (struct poptAlias*)malloc(sizeof(newAlias) * con->numAliases); else con->aliases = (struct poptAlias*)realloc(con->aliases, sizeof(newAlias) * con->numAliases); alias = con->aliases + aliasNum; alias->longName = (newAlias.longName) ? strcpy((char*)malloc(strlen(newAlias.longName) + 1), newAlias.longName) : NULL; alias->shortName = newAlias.shortName; alias->argc = newAlias.argc; alias->argv = newAlias.argv; return 0; } const char * poptBadOption(poptContext con, int flags) { struct optionStackEntry * os; if (flags & POPT_BADOPTION_NOALIAS) os = con->optionStack; else os = con->os; return os->argv[os->next - 1]; } #define POPT_ERROR_NOARG -10 #define POPT_ERROR_BADOPT -11 #define POPT_ERROR_OPTSTOODEEP -13 #define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ #define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ const char * /*const*/ poptStrerror(const int error) { switch (error) { case POPT_ERROR_NOARG: return POPT_("missing argument"); case POPT_ERROR_BADOPT: return POPT_("unknown option"); case POPT_ERROR_OPTSTOODEEP: return POPT_("aliases nested too deeply"); case POPT_ERROR_BADQUOTE: return POPT_("error in paramter quoting"); case POPT_ERROR_BADNUMBER: return POPT_("invalid numeric value"); case POPT_ERROR_OVERFLOW: return POPT_("number too large or too small"); case POPT_ERROR_ERRNO: return strerror(errno); default: return POPT_("unknown error"); } } int poptStuffArgs(poptContext con, const char ** argv) { int argc; if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; for (argc = 0; argv[argc]; argc++) ; con->os++; con->os->next = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = NULL; poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; con->os->stuffed = 1; return 0; } const char * poptGetInvocationName(poptContext con) { return con->os->argv[0]; } int poptStrippedArgv(poptContext con, int argc, char **argv) { int i,j=1, numargs=argc; for(i=1; iarg_strip)) { numargs--; } } for(i=1; iarg_strip)) { continue; } else { if(jbits) #define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) #define PBM_FREE(s) free(s); #define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) #define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) #define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) struct optionStackEntry { int argc; /*@only@*/ const char ** argv; /*@only@*/ pbm_set * argb; int next; /*@only@*/ const char * nextArg; /*@keep@*/ const char * nextCharArg; /*@dependent@*/ struct poptAlias * currAlias; int stuffed; }; struct execEntry { const char * longName; char shortName; const char * script; }; struct poptContext_s { struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; /*@dependent@*/ struct optionStackEntry * os; /*@owned@*/ const char ** leftovers; int numLeftovers; int nextLeftover; /*@keep@*/ const struct poptOption * options; int restLeftover; /*@only@*/ const char * appName; /*@only@*/ struct poptAlias * aliases; int numAliases; int flags; struct execEntry * execs; int numExecs; /*@only@*/ const char ** finalArgv; int finalArgvCount; int finalArgvAlloced; /*@dependent@*/ struct execEntry * doExec; /*@only@*/ const char * execPath; int execAbsolute; /*@only@*/ const char * otherHelp; pbm_set * arg_strip; }; #define xfree(_a) free((void *)_a) #ifdef HAVE_LIBINTL_H #include #endif #if defined(HAVE_GETTEXT) && !defined(__LCLINT__) #define _(foo) gettext(foo) #else #define _(foo) (foo) #endif #if defined(HAVE_DGETTEXT) && !defined(__LCLINT__) #define D_(dom, str) dgettext(dom, str) #define POPT_(foo) D_("popt", foo) #else #define POPT_(foo) (foo) #define D_(dom, str) (str) #endif #define N_(foo) (foo) #endif anon-proxy-00.05.38+20081230/CAControlChannelTest.hpp0000644000175000017500000000443410272122404020401 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifdef WITH_CONTROL_CHANNELS_TEST #include "CASyncControlChannel.hpp" /** A Control channel for testing if the control channels are working. * This channel simply reflects every message it receives. */ class CAControlChannelTest : public CASyncControlChannel { public: CAControlChannelTest(void); virtual ~CAControlChannelTest(void); /** Reflects the incoming message back to the sender*/ SINT32 processXMLMessage(DOM_Document& doc) { if(doc==NULL) return E_UNKNOWN; DOM_Element elemRoot=doc.getDocumentElement(); if(elemRoot==NULL) return E_UNKNOWN; //Hm, I am to stupid to do it better... DOM_Document* myDoc=new DOM_Document; *myDoc=DOM_Document::createDocument(); myDoc->appendChild(myDoc->importNode(elemRoot,true)); return sendXMLMessage(*myDoc); } }; #endif anon-proxy-00.05.38+20081230/CASocketAddr.hpp0000644000175000017500000000513710315744372016670 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CASOCKETADDR__ #define __CASOCKETADDR__ /** This is an abstract class for representing a socket address used in CASocket, CADatagramSocket and CAMuxSocket.*/ class CASocketAddr { public: virtual ~CASocketAddr(){} /**Creates a copy of the Address*/ virtual CASocketAddr* clone() const=0; /** The type (family) of socket for which this address is useful. * Must be overwritten in subclasses. **/ virtual SINT32 getType() const =0; /** The size of the SOCKADDR struct needed by function of CASocket and other.*/ virtual SINT32 getSize() const =0; /** Casts to a SOCKADDR struct **/ virtual const SOCKADDR* LPSOCKADDR() const =0; // virtual operator LPSOCKADDR()=0; /** Returns a string which describes this address in a human readable form. * @param buff buffer which stores the result * @param bufflen size of buff * @retval E_SUCCESS if successful * @retval E_SPACE if the buffer is to small * @retval E_UNKNOWN in case of an other error */ virtual SINT32 toString(UINT8* buff,UINT32 bufflen)const=0; }; typedef CASocketAddr* LPCASOCKETADDR; #endif anon-proxy-00.05.38+20081230/CACertStore.hpp0000644000175000017500000000447710766504165016571 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #ifndef __CA_CERTSTORE__ #define __CA_CERTSTORE__ #ifndef ONLY_LOCAL_PROXY #include "CACertificate.hpp" #define XML_X509DATA 2 struct __t_certstore_list { CACertificate* pCert; struct __t_certstore_list* next; }; typedef struct __t_certstore_list CERTSTORE_ENTRY; typedef CERTSTORE_ENTRY* LP_CERTSTORE_ENTRY; class CACertStore { public: CACertStore(); ~CACertStore(); SINT32 add(CACertificate* cert); CACertificate* getFirst(); CACertificate* getNext(); UINT32 getNumber(){return m_cCerts;} static CACertStore* decode(UINT8* buff,UINT32 bufflen,UINT32 type); SINT32 encode(UINT8* buff,UINT32* bufflen,UINT32 type); SINT32 encode(DOMElement* & elemnRoot,XERCES_CPP_NAMESPACE::DOMDocument* doc); private: LP_CERTSTORE_ENTRY m_pCertList; UINT32 m_cCerts; }; #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/INSTALL0000644000175000017500000000110307645276130014752 0ustar daviddavidFor installation and configuration instructions see: http://anon.inf.tu-dresden.de/develop/howtooperateamix.html ----------------------------------------------------------------------------------------- CVS: Developers with CVS write access should run doAutoReconf.sh whenever they check in changes to any of the automake/autoconf related files. Otherwise the timestamps of related files in the CVS repository will not be updated and a normal "make" will try run autoheader and automake. ----------------------------------------------------------------------------------------- anon-proxy-00.05.38+20081230/CALastMixChannelList.cpp0000644000175000017500000002447511047060555020351 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #ifndef ONLY_LOCAL_PROXY #include "CALastMixChannelList.hpp" #include "CAUtil.hpp" CALastMixChannelList::CALastMixChannelList() { m_HashTable=new LP_lmChannelListEntry[HASHTABLE_SIZE]; memset(m_HashTable,0, HASHTABLE_SIZE*sizeof(LP_lmChannelListEntry)); m_listSockets=NULL; m_listSocketsNext=NULL; m_nChannels=0; #ifdef DELAY_CHANNELS m_u32DelayChannelUnlimitTraffic=DELAY_CHANNEL_TRAFFIC; m_u32DelayChannelBucketGrow=DELAY_BUCKET_GROW; m_u32DelayChannelBucketGrowIntervall=DELAY_BUCKET_GROW_INTERVALL; m_pDelayBuckets=new UINT32*[MAX_POLLFD]; memset(m_pDelayBuckets,0,sizeof(UINT32*)*MAX_POLLFD); m_pMutexDelayChannel=new CAMutex(); m_pThreadDelayBucketsLoop=new CAThread((UINT8*)"Delay Buckets Thread"); m_bDelayBucketsLoopRun=true; m_pThreadDelayBucketsLoop->setMainLoop(lml_loopDelayBuckets); m_pThreadDelayBucketsLoop->start(this); #endif #ifdef DELAY_CHANNELS_LATENCY m_u32DelayChannelLatency=DELAY_CHANNEL_LATENCY; #endif } CALastMixChannelList::~CALastMixChannelList() { #ifdef DELAY_CHANNELS m_bDelayBucketsLoopRun=false; m_pThreadDelayBucketsLoop->join(); delete m_pThreadDelayBucketsLoop; m_pThreadDelayBucketsLoop = NULL; delete m_pMutexDelayChannel; m_pMutexDelayChannel = NULL; delete []m_pDelayBuckets; m_pDelayBuckets = NULL; #endif for(UINT32 i=0;i < HASHTABLE_SIZE; i++) { lmChannelListEntry* akt=m_HashTable[i]; lmChannelListEntry* tmp; while(akt!=NULL) { tmp=akt; akt=akt->list_Channels.next; delete tmp; tmp = NULL; } } delete[] m_HashTable; m_HashTable = NULL; } SINT32 CALastMixChannelList::add(HCHANNEL id,CASocket* pSocket,CASymCipher* pCipher,CAQueue* pQueue #ifdef LOG_CHANNEL ,UINT64 timecreated,UINT32 trafficInFromUser #endif #if defined(DELAY_CHANNELS_LATENCY) ,UINT64 delaytime #endif ) { UINT32 hash=id & HASH_MASK; lmChannelListEntry* pEntry=m_HashTable[hash]; lmChannelListEntry* pNewEntry=new lmChannelListEntry; pNewEntry->channelIn=id; pNewEntry->pCipher=pCipher; pNewEntry->pSocket=pSocket; pNewEntry->pQueueSend=pQueue; #if defined (LOG_CHANNEL) pNewEntry->timeCreated=timecreated; #endif #if defined (DELAY_CHANNELS_LATENCY) pNewEntry->timeLatency=delaytime+m_u32DelayChannelLatency; #endif #ifdef LOG_CHANNEL pNewEntry->trafficInFromUser=trafficInFromUser; pNewEntry->packetsDataInFromUser=1; pNewEntry->packetsDataOutToUser=0; pNewEntry->trafficOutToUser=0; #endif #ifdef NEW_FLOW_CONTROL pNewEntry->sendmeCounter=0; #endif #ifdef DELAY_CHANNELS pNewEntry->delayBucket=m_u32DelayChannelUnlimitTraffic; //can always send some first packets for(UINT32 i=0;idelayBucketID=i; break; } } m_pDelayBuckets[pNewEntry->delayBucketID]=&pNewEntry->delayBucket; #endif if(pEntry==NULL) //First Entry for Hash in HashTable { pNewEntry->list_Channels.next=NULL; pNewEntry->list_Channels.prev=NULL; } else //insert in Hashlist for Hashtableentry { pNewEntry->list_Channels.prev=NULL; pNewEntry->list_Channels.next=pEntry; pEntry->list_Channels.prev=pNewEntry; } //Insert in SocketList if(m_listSockets==NULL) { m_listSockets=pNewEntry; pNewEntry->list_Sockets.next=NULL; pNewEntry->list_Sockets.prev=NULL; } else { pNewEntry->list_Sockets.prev=NULL; pNewEntry->list_Sockets.next=m_listSockets; m_listSockets->list_Sockets.prev=pNewEntry; m_listSockets=pNewEntry; } m_HashTable[hash]=pNewEntry; //if(m_listSocketsNext==NULL) // m_listSocketsNext=m_listSockets; m_nChannels++; return E_SUCCESS; } SINT32 CALastMixChannelList::removeChannel(HCHANNEL channel) { UINT32 hash=channel & HASH_MASK; lmChannelListEntry* pEntry=m_HashTable[hash]; while(pEntry!=NULL) { if(pEntry->channelIn==channel) { if(m_listSocketsNext==pEntry) //removing next enumeration Element... m_listSocketsNext=m_listSocketsNext->list_Sockets.next; //adjusting! //remove from HashTable if(pEntry->list_Channels.prev==NULL) m_HashTable[hash]=pEntry->list_Channels.next; else { pEntry->list_Channels.prev->list_Channels.next=pEntry->list_Channels.next; } if(pEntry->list_Channels.next!=NULL) { pEntry->list_Channels.next->list_Channels.prev=pEntry->list_Channels.prev; } //remove from SocketList if(pEntry->list_Sockets.prev==NULL) m_listSockets=pEntry->list_Sockets.next; else pEntry->list_Sockets.prev->list_Sockets.next=pEntry->list_Sockets.next; if(pEntry->list_Sockets.next!=NULL) pEntry->list_Sockets.next->list_Sockets.prev=pEntry->list_Sockets.prev; #ifdef DELAY_CHANNELS m_pMutexDelayChannel->lock(); m_pDelayBuckets[pEntry->delayBucketID]=NULL; m_pMutexDelayChannel->unlock(); #endif delete pEntry; pEntry = NULL; m_nChannels--; return E_SUCCESS; } pEntry=pEntry->list_Channels.next; } return E_SUCCESS; } SINT32 CALastMixChannelList::test() { #if !defined (LOG_CHANNEL)&&!defined(DELAY_CHANNELS_LATENCY) CALastMixChannelList oList; UINT32 c; UINT32 rand; int i,j; for(i=0;i<100;i++) { getRandom(&c); oList.add(c,NULL,NULL,NULL); } for(i=0;i < 10000;i++) { lmChannelListEntry* akt=oList.getFirstSocket(); while(akt!=NULL) { getRandom(&rand); if(rand<0x7FFFFFFF) { getRandom(&c); oList.add(c,NULL,NULL,NULL); } getRandom(&rand); if(rand<0x7FFFFFFF) oList.removeChannel(akt->channelIn); getRandom(&rand); if(rand<0x0FFFFFFF) for(j=0;j<5;j++) { getRandom(&c); oList.add(c,NULL,NULL,NULL); } getRandom(&rand); if(rand<0x7FFFFFFF) for(j=0;j<10000;j++) { getRandom(&c); oList.removeChannel(c); } akt=oList.getNextSocket(); } } #endif return 0; } #ifdef DELAY_CHANNELS THREAD_RETURN lml_loopDelayBuckets(void* param) { CALastMixChannelList* pChannelList=(CALastMixChannelList*)param; UINT32** pDelayBuckets=pChannelList->m_pDelayBuckets; while(pChannelList->m_bDelayBucketsLoopRun) { pChannelList->m_pMutexDelayChannel->lock(); UINT32 u32BucketGrow=pChannelList->m_u32DelayChannelBucketGrow; UINT32 u32MaxBucket=u32BucketGrow*10; for(UINT32 i=0;im_pMutexDelayChannel->unlock(); msSleep(pChannelList->m_u32DelayChannelBucketGrowIntervall); } THREAD_RETURN_SUCCESS; } void CALastMixChannelList::reduceDelayBuckets(UINT32 delayBucketID, UINT32 amount) { m_pMutexDelayChannel->lock(); if(delayBucketID < MAX_POLLFD) { if(m_pDelayBuckets[delayBucketID] != NULL) { *(m_pDelayBuckets[delayBucketID]) -= ( (*(m_pDelayBuckets[delayBucketID])) > amount ) ? amount : (*(m_pDelayBuckets[delayBucketID])); } /*CAMsg::printMsg(LOG_DEBUG,"DelayBuckets decrementing ID %u downto %u\n", delayBucketID, (*(m_pDelayBuckets[delayBucketID])) );*/ } m_pMutexDelayChannel->unlock(); } UINT32 CALastMixChannelList::getDelayBuckets(UINT32 delayBucketID) { UINT32 ret = 0; m_pMutexDelayChannel->lock(); ret = ( (*(m_pDelayBuckets[delayBucketID])) > 0 ) ? (*(m_pDelayBuckets[delayBucketID])) : 0; m_pMutexDelayChannel->unlock(); return ret; } bool CALastMixChannelList::hasDelayBuckets(UINT32 delayBucketID) { bool ret = false; m_pMutexDelayChannel->lock(); if(delayBucketID < MAX_POLLFD) { if(m_pDelayBuckets[delayBucketID] != NULL) { ret = ( (*(m_pDelayBuckets[delayBucketID])) > 0 ); } } m_pMutexDelayChannel->unlock(); return ret; } void CALastMixChannelList::setDelayParameters(UINT32 unlimitTraffic,UINT32 bucketGrow,UINT32 intervall) { m_pMutexDelayChannel->lock(); CAMsg::printMsg(LOG_DEBUG,"CALastMixChannelList - Set new traffic limit per channel- unlimit: %u bucketgrow: %u intervall %u\n", unlimitTraffic,bucketGrow,intervall); m_u32DelayChannelUnlimitTraffic=unlimitTraffic; m_u32DelayChannelBucketGrow=bucketGrow; m_u32DelayChannelBucketGrowIntervall=intervall; for(UINT32 i=0;iunlock(); } #endif #ifdef DELAY_CHANNELS_LATENCY void CALastMixChannelList::setDelayLatencyParameters(UINT32 latency) { CAMsg::printMsg(LOG_DEBUG,"CALastMixChannelList - Set new latency: %u ms\n",latency); m_u32DelayChannelLatency=latency; } #endif #endif //ONLY_LOCAL_PROXY anon-proxy-00.05.38+20081230/CADatagramSocket.cpp0000644000175000017500000000741407524233765017540 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #include "CADatagramSocket.hpp" #include "CASocketAddrINet.hpp" #ifdef _DEBUG extern int sockets; #include "CAMsg.hpp" #endif CADatagramSocket::CADatagramSocket() { m_Socket=0; // localPort=-1; } SINT32 CADatagramSocket::create() { return create(AF_INET); } SINT32 CADatagramSocket::create(int type) { if(m_Socket==0) m_Socket=::socket(type,SOCK_DGRAM,0); if(m_Socket==INVALID_SOCKET) return SOCKET_ERROR; // localPort=-1; return E_SUCCESS; } SINT32 CADatagramSocket::close() { // EnterCriticalSection(&csClose); // localPort=-1; int ret; if(m_Socket!=0) { /* LINGER linger; linger.l_onoff=1; linger.l_linger=0; if(::setsockopt(m_Socket,SOL_SOCKET,SO_LINGER,(char*)&linger,sizeof(linger))!=0) CAMsg::printMsg(LOG_DEBUG,"Fehler bei setsockopt - LINGER!\n"); */ ::closesocket(m_Socket); #ifdef _DEBUG sockets--; #endif m_Socket=0; ret=0; } else ret=SOCKET_ERROR; // LeaveCriticalSection(&csClose); return ret; } SINT32 CADatagramSocket::bind(CASocketAddr & from) { // localPort=-1; if(m_Socket==0&&create(from.getType())!=E_SUCCESS) return SOCKET_ERROR; if(::bind(m_Socket,from.LPSOCKADDR(),from.getSize())==SOCKET_ERROR) return SOCKET_ERROR; return E_SUCCESS; } SINT32 CADatagramSocket::bind(UINT16 port) { CASocketAddrINet oSocketAddr(port); return bind(oSocketAddr); } SINT32 CADatagramSocket::send(UINT8* buff,UINT32 len,CASocketAddr & to) { if(::sendto(m_Socket,(char*)buff,len,MSG_NOSIGNAL,to.LPSOCKADDR(),to.getSize())==SOCKET_ERROR) return E_UNKNOWN; return E_SUCCESS; } SINT32 CADatagramSocket::receive(UINT8* buff,UINT32 len,CASocketAddr* from) { int ret; if(from!=NULL) { socklen_t fromlen=from->getSize(); ret=::recvfrom(m_Socket,(char*)buff,len,MSG_NOSIGNAL,(LPSOCKADDR)from,&fromlen); } else { ret=::recv(m_Socket,(char*)buff,len,MSG_NOSIGNAL); } return ret; } /* SINT32 CADatagramSocket::getLocalPort() { if(localPort==-1) { struct sockaddr_in addr; socklen_t namelen=sizeof(struct sockaddr_in); if(getsockname(m_Socket,(struct sockaddr*)&addr,&namelen)==SOCKET_ERROR) return SOCKET_ERROR; else localPort=ntohs(addr.sin_port); } return localPort; } */ anon-proxy-00.05.38+20081230/CACmdLnOptions.cpp0000644000175000017500000036231011126514131017175 0ustar daviddavid/* Copyright (c) 2000, The JAP-Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #include "StdAfx.h" #include "CACmdLnOptions.hpp" #include "CAUtil.hpp" #include "CAMix.hpp" #include "CAMsg.hpp" #include "CASocketAddrINet.hpp" #include "CASocket.hpp" #include "CAXMLBI.hpp" #include "xml/DOM_Output.hpp" #include "CABase64.hpp" #include "CADynaNetworking.hpp" //#ifdef LOG_CRIME #include "tre/regex.h" //#endif CACmdLnOptions::CACmdLnOptions() { m_bDaemon=false; m_bSyslog=false; m_bSocksSupport = false; m_bLocalProxy=m_bFirstMix=m_bLastMix=m_bMiddleMix=false; #ifndef ONLY_LOCAL_PROXY m_bIsRunReConfigure=false; m_addrInfoServices = NULL; m_addrInfoServicesSize=0; m_pcsReConfigure=new CAMutex(); m_pSignKey=NULL; m_pOwnCertificate=NULL; m_OpCert=NULL; m_pPrevMixCertificate=NULL; m_pNextMixCertificate=NULL; m_bCompressedLogs=false; m_pLogEncryptionCertificate=NULL; m_bIsEncryptedLogEnabled=false; m_docMixInfo= createDOMDocument(); m_docMixXml=NULL; m_docOpTnCs=NULL; //Operator Terms and Conditions (if any) m_bAcceptReconfiguration=false; m_maxNrOfUsers = 0; #ifdef COUNTRY_STATS m_dbCountryStatsHost=m_dbCountryStatsPasswd=m_dbCountryStatsUser=NULL; #endif #endif //ONLY_LOCAL_PROXY m_iTargetPort=m_iSOCKSPort=m_iSOCKSServerPort=0xFFFF; m_strTargetHost=m_strSOCKSHost=NULL; m_strUser=NULL; m_strCascadeName=NULL; m_strLogDir=NULL; m_perfTestEnabled=true; setZero64(m_maxLogFileSize); m_strEncryptedLogDir=NULL; m_arTargetInterfaces=NULL; m_cnTargets=0; m_arListenerInterfaces=NULL; m_cnListenerInterfaces=0; m_arStrVisibleAddresses=NULL; m_cnVisibleAddresses=0; m_nrOfOpenFiles=-1; m_strMixID=NULL; m_strMixName=NULL; m_bAutoReconnect=false; m_strConfigFile=NULL; m_strPidFile=NULL; m_bAutoRestart=false; #ifdef PAYMENT m_pBI=NULL; m_strDatabaseHost=NULL; m_strDatabaseName=NULL; m_strDatabaseUser=NULL; m_strDatabasePassword=NULL; m_strAiID=NULL; #endif #ifdef SERVER_MONITORING m_strMonitoringListenerHost = NULL; m_iMonitoringListenerPort = 0xFFFF; #endif #ifdef LOG_CRIME m_arCrimeRegExpsURL=NULL; m_nCrimeRegExpsURL=0; m_arCrimeRegExpsPayload=NULL; m_nCrimeRegExpsPayload=0; #endif #ifdef DATA_RETENTION_LOG m_strDataRetentionLogDir=NULL; #endif #ifdef DYNAMIC_MIX m_strLastCascadeProposal = NULL; #endif #if defined(DELAY_CHANNELS) && defined(DELAY_USERS) if(isFirstMix()) { m_u32DelayChannelUnlimitTraffic=DELAY_USERS_TRAFFIC; m_u32DelayChannelBucketGrow=DELAY_USERS_BUCKET_GROW; m_u32DelayChannelBucketGrowIntervall=DELAY_USERS_BUCKET_GROW_INTERVALL; } else { m_u32DelayChannelUnlimitTraffic=DELAY_CHANNEL_TRAFFIC; m_u32DelayChannelBucketGrow=DELAY_BUCKET_GROW; m_u32DelayChannelBucketGrowIntervall=DELAY_BUCKET_GROW_INTERVALL; } #elif defined(DELAY_CHANNELS) m_u32DelayChannelUnlimitTraffic=DELAY_CHANNEL_TRAFFIC; m_u32DelayChannelBucketGrow=DELAY_BUCKET_GROW; m_u32DelayChannelBucketGrowIntervall=DELAY_BUCKET_GROW_INTERVALL; #elif defined (DELAY_USERS) m_u32DelayChannelUnlimitTraffic=DELAY_USERS_TRAFFIC; m_u32DelayChannelBucketGrow=DELAY_USERS_BUCKET_GROW; m_u32DelayChannelBucketGrowIntervall=DELAY_USERS_BUCKET_GROW_INTERVALL; #endif #if defined(DELAY_CHANNELS_LATENCY) m_u32DelayChannelLatency = DELAY_CHANNEL_LATENCY; #endif /* initialize pointer to option setter functions */ initMainOptionSetters(); initGeneralOptionSetters(); initCertificateOptionSetters(); initAccountingOptionSetters(); initNetworkOptionSetters(); initCrimeDetectionOptionSetters(); } CACmdLnOptions::~CACmdLnOptions() { cleanup(); } void CACmdLnOptions::initMainOptionSetters() { mainOptionSetters = new optionSetter_pt[MAIN_OPTION_SETTERS_NR]; int count = -1; mainOptionSetters[++count]= &CACmdLnOptions::setGeneralOptions; mainOptionSetters[++count]= &CACmdLnOptions::setMixDescription; mainOptionSetters[++count]= &CACmdLnOptions::setCertificateOptions; mainOptionSetters[++count]= &CACmdLnOptions::setAccountingOptions; mainOptionSetters[++count]= &CACmdLnOptions::setNetworkOptions; mainOptionSetters[++count]= &CACmdLnOptions::setRessourceOptions; mainOptionSetters[++count]= &CACmdLnOptions::setTermsAndConditions; mainOptionSetters[++count]= &CACmdLnOptions::setCrimeDetectionOptions; } void CACmdLnOptions::initGeneralOptionSetters() { generalOptionSetters = new optionSetter_pt[GENERAL_OPTIONS_NR]; int count = -1; generalOptionSetters[++count]= &CACmdLnOptions::setMixType; generalOptionSetters[++count]= &CACmdLnOptions::setMixName; generalOptionSetters[++count]= &CACmdLnOptions::setMixID; generalOptionSetters[++count]= &CACmdLnOptions::setDynamicMix; generalOptionSetters[++count]= &CACmdLnOptions::setMinCascadeLength; generalOptionSetters[++count]= &CACmdLnOptions::setCascadeNameFromOptions; generalOptionSetters[++count]= &CACmdLnOptions::setUserID; generalOptionSetters[++count]= &CACmdLnOptions::setNrOfFileDescriptors; generalOptionSetters[++count]= &CACmdLnOptions::setDaemonMode; generalOptionSetters[++count]= &CACmdLnOptions::setMaxUsers; generalOptionSetters[++count]= &CACmdLnOptions::setLoggingOptions; } void CACmdLnOptions::initCertificateOptionSetters() { certificateOptionSetters = new optionSetter_pt[CERTIFICATE_OPTIONS_NR]; int count = -1; certificateOptionSetters[++count]= &CACmdLnOptions::setOwnCertificate; certificateOptionSetters[++count]= &CACmdLnOptions::setOwnOperatorCertificate; certificateOptionSetters[++count]= &CACmdLnOptions::setNextMixCertificate; certificateOptionSetters[++count]= &CACmdLnOptions::setPrevMixCertificate; } void CACmdLnOptions::initAccountingOptionSetters() { accountingOptionSetters = new optionSetter_pt[ACCOUNTING_OPTIONS_NR]; int count = -1; accountingOptionSetters[++count]= &CACmdLnOptions::setPriceCertificate; accountingOptionSetters[++count]= &CACmdLnOptions::setPaymentInstance; accountingOptionSetters[++count]= &CACmdLnOptions::setAccountingSoftLimit; accountingOptionSetters[++count]= &CACmdLnOptions::setAccountingHardLimit; accountingOptionSetters[++count]= &CACmdLnOptions::setPrepaidInterval; accountingOptionSetters[++count]= &CACmdLnOptions::setSettleInterval; accountingOptionSetters[++count]= &CACmdLnOptions::setAccountingDatabase; } void CACmdLnOptions::initNetworkOptionSetters() { networkOptionSetters = new optionSetter_pt[NETWORK_OPTIONS_NR]; int count = -1; networkOptionSetters[++count]= &CACmdLnOptions::setInfoServices; networkOptionSetters[++count]= &CACmdLnOptions::setListenerInterfaces; networkOptionSetters[++count]= &CACmdLnOptions::setTargetInterfaces; networkOptionSetters[++count]= &CACmdLnOptions::setServerMonitoring; networkOptionSetters[++count]= &CACmdLnOptions::setKeepAliveTraffic; networkOptionSetters[++count]= &CACmdLnOptions::setPerformanceTestEnabled; } void CACmdLnOptions::initCrimeDetectionOptionSetters() { crimeDetectionOptionSetters = new optionSetter_pt[NETWORK_OPTIONS_NR]; int count = -1; crimeDetectionOptionSetters[++count]= &CACmdLnOptions::setCrimeURLRegExp; crimeDetectionOptionSetters[++count]= &CACmdLnOptions::setCrimePayloadRegExp; } /** This is the final cleanup, which deletes every resource (including any locks necessary to synchronise read/write to properties). */ SINT32 CACmdLnOptions::cleanup() { clean(); #ifndef ONLY_LOCAL_PROXY delete m_pcsReConfigure; m_pcsReConfigure=NULL; #endif return E_SUCCESS; } /** Deletes all information about the target interfaces. */ SINT32 CACmdLnOptions::clearTargetInterfaces() { if(m_arTargetInterfaces!=NULL) { for(UINT32 i=0;i element given. * The structur is as follows: *@verbatim * * * * * * * * * @endverbatim */ SINT32 CACmdLnOptions::addVisibleAddresses(DOMNode* nodeProxy) { if(nodeProxy==NULL) return E_UNKNOWN; ASSERT_PARENT_NODE_NAME (nodeProxy->getNodeName(), OPTIONS_NODE_PROXY, OPTIONS_NODE_VISIBLE_ADDRESS_LIST); DOMNode* elemVisAdresses=NULL; getDOMChildByName(nodeProxy, OPTIONS_NODE_VISIBLE_ADDRESS_LIST, elemVisAdresses); DOMNode* elemVisAddress=NULL; getDOMChildByName(elemVisAdresses, OPTIONS_NODE_VISIBLE_ADDRESS ,elemVisAddress); while(elemVisAddress!=NULL) { if(equals(elemVisAddress->getNodeName(), OPTIONS_NODE_VISIBLE_ADDRESS)) { DOMElement* elemHost; if(getDOMChildByName(elemVisAddress, OPTIONS_NODE_HOST ,elemHost)==E_SUCCESS) { UINT8 tmp[TMP_BUFF_SIZE]; UINT32 len = TMP_BUFF_SIZE; if(getDOMElementValue(elemHost,tmp,&len)==E_SUCCESS) {//append the new address to the list of addresses UINT8** tmpAr=new UINT8*[m_cnVisibleAddresses+1]; if(m_arStrVisibleAddresses!=NULL) { memcpy(tmpAr,m_arStrVisibleAddresses,m_cnVisibleAddresses*sizeof(UINT8*)); delete[] m_arStrVisibleAddresses; m_arStrVisibleAddresses = NULL; } tmpAr[m_cnVisibleAddresses]=new UINT8[len+1]; memcpy(tmpAr[m_cnVisibleAddresses],tmp,len+1); m_cnVisibleAddresses++; m_arStrVisibleAddresses=tmpAr; } } } elemVisAddress=elemVisAddress->getNextSibling(); } return E_SUCCESS; } SINT32 CACmdLnOptions::getVisibleAddress(UINT8* strAddressBuff, UINT32 len,UINT32 nr) { if(strAddressBuff==NULL||nr==0||nr>m_cnVisibleAddresses) { return E_UNKNOWN; } if(strlen((char*)m_arStrVisibleAddresses[nr-1] )>=len) { return E_SPACE; } strcpy((char*)strAddressBuff,(char*)m_arStrVisibleAddresses[nr-1]); return E_SUCCESS; } #endif //ONLY_LOCAL_PROXY /** Deletes all resssource allocated by objects of this class EXPECT the locks necessary to controll access to the properties of this class*/ void CACmdLnOptions::clean() { delete[] m_strConfigFile; m_strConfigFile=NULL; delete[] m_strTargetHost; m_strTargetHost=NULL; delete[] m_strSOCKSHost; m_strSOCKSHost=NULL; #ifndef ONLY_LOCAL_PROXY if (m_addrInfoServices != NULL) { for (UINT32 i = 0; i < m_addrInfoServicesSize; i++) { delete m_addrInfoServices[i]; m_addrInfoServices[i] = NULL; } delete[] m_addrInfoServices; m_addrInfoServices=NULL; m_addrInfoServicesSize = 0; } #endif //ONLY_LOCAL_PROXY delete[] m_strCascadeName; m_strCascadeName=NULL; delete[] m_strLogDir; m_strLogDir=NULL; delete[] m_strPidFile; m_strPidFile=NULL; delete[] m_strEncryptedLogDir; m_strEncryptedLogDir=NULL; delete[] m_strUser; m_strUser=NULL; delete[] m_strMixID; m_strMixID=NULL; delete[] m_strMixName; m_strMixName=NULL; clearTargetInterfaces(); clearListenerInterfaces(); #ifndef ONLY_LOCAL_PROXY if(m_docMixInfo!=NULL) m_docMixInfo=NULL; clearVisibleAddresses(); delete m_pSignKey; m_pSignKey=NULL; delete m_pOwnCertificate; m_pOwnCertificate=NULL; delete m_OpCert; m_OpCert=NULL; delete m_pNextMixCertificate; m_pNextMixCertificate=NULL; delete m_pPrevMixCertificate; m_pPrevMixCertificate=NULL; delete m_pLogEncryptionCertificate; m_pLogEncryptionCertificate=NULL; if(m_docMixInfo!=NULL) { m_docMixInfo->release(); m_docMixInfo=NULL; } if(m_docMixXml!=NULL) { m_docMixXml->release(); m_docMixXml=NULL; } if(m_docOpTnCs!=NULL) { m_docOpTnCs->release(); m_docOpTnCs=NULL; } #ifdef COUNTRY_STATS delete[] m_dbCountryStatsHost; m_dbCountryStatsHost = NULL; delete[] m_dbCountryStatsUser; m_dbCountryStatsUser = NULL; delete[] m_dbCountryStatsPasswd; m_dbCountryStatsPasswd = NULL; #endif #ifdef DATA_RETENTION_LOG delete[] m_strDataRetentionLogDir; m_strDataRetentionLogDir=NULL; #endif #endif //ONLY_LOCAL_PROXY #ifdef SERVER_MONITORING if(m_strMonitoringListenerHost != NULL) { delete[] m_strMonitoringListenerHost; m_strMonitoringListenerHost = NULL; } #endif delete [] mainOptionSetters; mainOptionSetters = NULL; delete [] generalOptionSetters; generalOptionSetters = NULL; delete certificateOptionSetters; certificateOptionSetters = NULL; delete [] accountingOptionSetters; accountingOptionSetters = NULL; delete [] networkOptionSetters; networkOptionSetters = NULL; } SINT32 CACmdLnOptions::parse(int argc,const char** argv) { int iDaemon=0; char* target=NULL; int iLocalProxy=0; int SOCKSport=-1; char* socks=NULL; char* logdir=NULL; int iCompressedLogs=0; char* serverPort=NULL; int iVersion=0; char* configfile=NULL; int iAutoReconnect=0; int iAutoRestart=0; char* strPidFile=NULL; char* strCreateConf=0; //DOM_Document docMixXml; poptOption theOptions[]= { {"localproxy",'j',POPT_ARG_NONE,&iLocalProxy,0,"act as local proxy",NULL}, {"daemon",'d',POPT_ARG_NONE,&iDaemon,0,"start as daemon [only for local proxy]",NULL}, {"next",'n',POPT_ARG_STRING,&target,0,"first mix of cascade [only for local proxy]",""}, {"autoreconnect",'a',POPT_ARG_NONE,&iAutoReconnect,0,"auto reconnects if connection to first mix was lost [only for local proxy]",NULL}, {"port",'p',POPT_ARG_STRING,&serverPort,0,"listening on [host:]port|path [only for local proxy]","<[host:]port|path>"}, {"socksport",'s',POPT_ARG_INT,&SOCKSport,0,"listening port for socks",""}, {"logdir",'l',POPT_ARG_STRING,&logdir,0,"directory where log files go to [only for local proxy]",""}, #ifdef COMPRESSED_LOGS {"gzip",'z',POPT_ARG_NONE,&iCompressedLogs,0,"create gziped logs",NULL}, #endif {"config",'c',POPT_ARG_STRING,&configfile,0,"config file to use [for a real Mix in a cascade]",""}, {"version",'v',POPT_ARG_NONE,&iVersion,0,"show version",NULL}, {"pidfile",'r',POPT_ARG_STRING,&strPidFile,0,"file where the PID will be stored",""}, {"createConf",0,POPT_ARG_STRING,&strCreateConf,0,"creates a generic configuration for MixOnCD","[]"}, {"autorestart",0,POPT_ARG_NONE,&iAutoRestart,0,"restarts the Mix process if it dies unexpectly",NULL}, POPT_AUTOHELP {NULL,0,0, NULL,0,NULL,NULL} }; poptContext ctx=poptGetContext(NULL,argc,argv,theOptions,0); SINT32 ret=poptGetNextOpt(ctx); while(ret==POPT_ERROR_BADOPT) ret=poptGetNextOpt(ctx); poptFreeContext(ctx); if(iVersion!=0) { printf(MIX_VERSION_INFO); for(UINT32 t=0;t<10000;t++) { CASocket* pSocket=new CASocket; if(pSocket->create(false)!=E_SUCCESS) { printf("Max open sockets: %u\n",t); exit(0); } } printf("Max open sockets: >10000\n"); exit(0); } #ifndef ONLY_LOCAL_PROXY if(strCreateConf!=NULL) { createMixOnCDConfiguration((UINT8*)strCreateConf); exit(0); } #endif if(iLocalProxy!=0) m_bLocalProxy=true; if(m_bLocalProxy&&iAutoReconnect!=0) m_bAutoReconnect=true; /* LERNGRUPPE: Also try to use default config file for Mix Category 1 */ if(configfile == NULL) { configfile = (char*) malloc(sizeof(char) * (strlen(DEFAULT_CONFIG_FILE)+1)); strncpy(configfile, DEFAULT_CONFIG_FILE, (strlen(DEFAULT_CONFIG_FILE)+1)); #if defined (_WIN32) &&!defined(__CYGWIN__) // R_OK is not defined in Windows POSIX implementation #define R_OK 4 #endif int err = access(configfile, R_OK); if( err ) { if(configfile != NULL) { free(configfile); configfile = NULL; } } } /* END LERNGRUPPE */ if(configfile!=NULL) { #ifndef ONLY_LOCAL_PROXY ret=readXmlConfiguration(m_docMixXml,(UINT8*)configfile); if(ret==E_FILE_OPEN) CAMsg::printMsg(LOG_CRIT,"Could not open config file: %s\n",configfile); else if(ret==E_FILE_READ) CAMsg::printMsg(LOG_CRIT,"Could not read config file: %s\n",configfile); else if(ret==E_XML_PARSE) CAMsg::printMsg(LOG_CRIT,"Could not parse config file: %s\n",configfile); else { m_strConfigFile=new UINT8[strlen(configfile)+1]; memcpy(m_strConfigFile,configfile,strlen(configfile)+1); } #endif free(configfile); } if(iDaemon==0) m_bDaemon=false; else m_bDaemon=true; if(target!=NULL) { if(target[0]=='/') //Unix Domain Sockaet { m_strTargetHost=new char[strlen(target)+1]; strcpy(m_strTargetHost,target); } else { char tmpHostname[TMP_BUFF_SIZE]; SINT32 tmpPort; char* tmpStr1=strchr(target,':'); if(tmpStr1!=NULL) { memcpy(tmpHostname,target,tmpStr1-target); tmpHostname[tmpStr1-target]=0; tmpPort=(SINT32)atol(tmpStr1+1); } else {//TODO what if not in right form ? //try if it is a number --> use it as port //and use 'localhost' as traget-host tmpPort=(SINT32)atol(target); if(tmpPort!=0) //we get it { strcpy(tmpHostname,"localhost"); } else //we try to use it as host and use the default port { /* LERNGRUPPE moved the define to CACmdLnOption.hpp because we need it elsewhere too */ //#define DEFAULT_TARGET_PORT 6544 tmpPort=DEFAULT_TARGET_PORT; strcpy(tmpHostname,target); } } m_strTargetHost=new char[strlen(tmpHostname)+1]; strcpy(m_strTargetHost,tmpHostname); m_iTargetPort=(UINT16)tmpPort; } free(target); } if(socks!=NULL) { char* tmpStr; if((tmpStr=strchr(socks,':'))!=NULL) { m_strSOCKSHost=new char[tmpStr-socks+1]; (*tmpStr)=0; strcpy(m_strSOCKSHost,socks); m_iSOCKSPort=(UINT16)atol(tmpStr+1); } free(socks); } if(logdir!=NULL) { m_strLogDir=new char[strlen(logdir)+1]; strcpy(m_strLogDir,logdir); free(logdir); } if(strPidFile!=NULL) { m_strPidFile=new char[strlen(strPidFile)+1]; strcpy(m_strPidFile,strPidFile); free(strPidFile); } if(iCompressedLogs==0) m_bCompressedLogs=false; else m_bCompressedLogs=true; if(iAutoRestart==0) m_bAutoRestart=false; else m_bAutoRestart=true; if(serverPort!=NULL&&m_bLocalProxy) { m_arListenerInterfaces=new CAListenerInterface*[1]; m_arListenerInterfaces[0]=NULL; m_cnListenerInterfaces=0; char* tmpStr; if(serverPort[0]=='/') //Unix Domain Socket { m_arListenerInterfaces[0]=CAListenerInterface::getInstance(RAW_UNIX,(UINT8*)serverPort); } else //Internet Socket { char* strServerHost=NULL; SINT32 iServerPort; if((tmpStr=strchr(serverPort,':'))!=NULL) //host:port { strServerHost=new char[tmpStr-serverPort+1]; (*tmpStr)=0; strcpy(strServerHost,serverPort); iServerPort=(SINT32)atol(tmpStr+1); } else //port only ? { iServerPort=(SINT32)atol(serverPort); } m_arListenerInterfaces[0]=CAListenerInterface::getInstance(RAW_TCP,(UINT8*)strServerHost,(UINT16)iServerPort); delete [] strServerHost; strServerHost = NULL; } free(serverPort); if(m_arListenerInterfaces[0]!=0) m_cnListenerInterfaces=1; } m_iSOCKSServerPort=(UINT16)SOCKSport; #ifndef ONLY_LOCAL_PROXY if(!m_bLocalProxy) { ret=processXmlConfiguration(m_docMixXml); #ifndef DYNAMIC_MIX if(ret!=E_SUCCESS) return ret; } #else /* LERNGRUPPE: Let's try to recover and build a default configuration */ if(ret!=E_SUCCESS) { createDefaultConfiguration(); ret=processXmlConfiguration(m_docMixXml); if(ret!=E_SUCCESS) return ret; } } #endif /* Try to read InfoService configuration from external file infoservices.xml */ XERCES_CPP_NAMESPACE::DOMDocument* infoservices; if( readXmlConfiguration(infoservices,(UINT8*)"infoservices.xml") == E_SUCCESS ) { CAMsg::printMsg(LOG_DEBUG, "Will now get InfoServices from infoservices.xml (this overrides the InfoServices from the default config!)\n"); DOMElement* elemIs=infoservices->getDocumentElement(); parseInfoServices(elemIs); } #ifdef DYNAMIC_MIX /* Ok, at this point we should make sure that we have a minimal configuration. If not we try to fill up the missing parameters with default values*/ if( checkCertificates() != E_SUCCESS ) { CAMsg::printMsg(LOG_CRIT, "I was not able to get a working certificate, please check the configuration! Exiting now\n"); exit(0); } UINT32 running = 0; CAMsg::printMsg( LOG_INFO, "I will now test if I have enough information about InfoServices...\n"); if( checkInfoServices(&running) != E_SUCCESS ) { /** @todo what shall the mix-operator do? ask AN.ON team? */ CAMsg::printMsg(LOG_CRIT, "Problems with InfoServices\nI need at least %i running InfoServices, but i only know about %i at the moment.\n", MIN_INFOSERVICES, running); exit(0); } CAMsg::printMsg( LOG_INFO, "InfoService information ok\n"); if( checkListenerInterfaces() != E_SUCCESS ) { CAMsg::printMsg(LOG_CRIT, "I don't have any usefull ListenerInterfaces and I canot determine one. please check the configuration! Hints should have been given\n"); exit(0); } if( checkMixId() != E_SUCCESS) { CAMsg::printMsg(LOG_CRIT, "ARGS, I don't have an unique ID, cannot create one! Exiting now\n"); exit(0); } #endif // DYNAMIC_MIX #endif //ONLY_LOCAL_PROXY return E_SUCCESS; } #ifndef ONLY_LOCAL_PROXY struct t_CMNDLN_REREAD_PARAMS { CACmdLnOptions* pCmdLnOptions; CAMix* pMix; }; #endif //ONLY_LOCAL_PROXY /** Copies options from \c newOptions. Only those options which are specified * in \c newOptions are copied. The others are left untouched! * * @param newOptions \c CACmdLnOptions object from which the new values are copied * @retval E_UNKNOWN if an error occurs * @retval E_SUCCESS otherwise */ SINT32 CACmdLnOptions::setNewValues(CACmdLnOptions& newOptions) { //Copy Targets if(newOptions.getTargetInterfaceCount()>0) { clearTargetInterfaces(); m_cnTargets=newOptions.getTargetInterfaceCount(); m_arTargetInterfaces=new TargetInterface[m_cnTargets]; for(UINT32 i=0;igetDocumentElement(); //getCertificates if given... DOMElement* elemSig; getDOMChildByName(elemRoot, OPTIONS_NODE_SIGNATURE, elemSig, false); //Own Certiticate first //nextMixCertificate if given DOMElement* elemCert; getDOMChildByName(elemSig, OPTIONS_NODE_X509DATA, elemCert,true); if(elemSig!=NULL) m_pNextMixCertificate = CACertificate::decode(elemCert->getFirstChild(),CERT_X509CERTIFICATE); DOMElement* elemOptionsRoot = m_docMixXml->getDocumentElement(); DOMElement* elemOptionsCerts; getDOMChildByName(elemOptionsRoot, OPTIONS_NODE_CERTIFICATE_LIST, elemOptionsCerts, false); DOMElement* elemOptionsNextMixCert; if(getDOMChildByName(elemOptionsRoot, OPTIONS_NODE_NEXT_MIX_CERTIFICATE, elemOptionsNextMixCert, false) != E_SUCCESS) { elemOptionsNextMixCert = createDOMElement(m_docMixXml, OPTIONS_NODE_NEXT_MIX_CERTIFICATE); elemOptionsCerts->appendChild(elemOptionsNextMixCert); elemOptionsNextMixCert->appendChild(m_docMixXml->importNode(elemCert->getFirstChild(),true)); } else { if(elemOptionsNextMixCert->hasChildNodes()) { elemOptionsNextMixCert->replaceChild(m_docMixXml->importNode(elemCert->getFirstChild(),true), elemOptionsNextMixCert->getFirstChild()); } else { elemOptionsNextMixCert->appendChild(m_docMixXml->importNode(elemCert->getFirstChild(),true)); } } CAMsg::printMsg(LOG_DEBUG,"setNextMix() - certificates done\n"); DOMElement* elemNextMix; getDOMChildByName(elemRoot, OPTIONS_NODE_LISTENER_INTERFACE, elemNextMix,true); DOMElement* elemOptionsNetwork; DOMElement* elemOptionsNextMixInterface; if(getDOMChildByName(elemOptionsRoot, OPTIONS_NODE_NETWORK, elemOptionsNetwork, false) != E_SUCCESS) { elemOptionsNetwork = createDOMElement(m_docMixXml, OPTIONS_NODE_NETWORK); elemOptionsRoot->appendChild(elemOptionsNetwork); } if(getDOMChildByName(elemOptionsNetwork, OPTIONS_NODE_NEXT_MIX, elemOptionsNextMixInterface, false) != E_SUCCESS) { elemOptionsNextMixInterface = createDOMElement(m_docMixXml, OPTIONS_NODE_NEXT_MIX); elemOptionsNetwork->appendChild(elemOptionsNextMixInterface); } else { while(elemOptionsNextMixInterface->hasChildNodes()) { elemOptionsNextMixInterface->removeChild(elemOptionsNextMixInterface->getFirstChild()); } } DOMNode* interfaceData = elemNextMix->getFirstChild(); while(interfaceData != NULL) { elemOptionsNextMixInterface->appendChild(m_docMixXml->importNode(interfaceData,true)); interfaceData = interfaceData->getNextSibling(); } CAMsg::printMsg(LOG_DEBUG,"setNextMix() - end\n"); return processXmlConfiguration(m_docMixXml); } #else //DYNAMIC_MIX SINT32 CACmdLnOptions::setNextMix(DOM_Document& doc) { resetNextMix(); /** First set the next mix's certificate */ DOM_Element elemRoot = doc.getDocumentElement(); //getCertificates if given... DOM_Element elemSig; getDOMChildByName(elemRoot,(UINT8*) OPTIONS_NODE_SIGNATURE, elemSig, false); DOM_Element elemCert; getDOMChildByName(elemSig,(UINT8*) OPTIONS_NODE_X509DATA, elemCert, true); if(elemCert!=NULL) m_pNextMixCertificate = CACertificate::decode(elemCert.getFirstChild(),CERT_X509CERTIFICATE); /** Now import the next mix's network stuff */ DOM_Node elemNextMix; DOM_Element elemListeners; // Search through the ListenerInterfaces an use a non-hidden one! getDOMChildByName(elemRoot,(UINT8*) OPTIONS_NODE_LISTENER_INTERFACE_LIST, elemListeners, true); DOM_NodeList nlListenerInterfaces = elemListeners.getElementsByTagName(CAListenerInterface::XML_ELEMENT_NAME); UINT32 len = nlListenerInterfaces.getLength(); bool foundNonHiddenInterface = false; for(UINT32 i=0;i