• Main Page
  • Related Pages
  • Modules
  • Classes
  • Files
  • Directories

CACmdLnOptions.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000, The JAP-Team
00003 All rights reserved.
00004 Redistribution and use in source and binary forms, with or without modification,
00005 are permitted provided that the following conditions are met:
00006 
00007   - Redistributions of source code must retain the above copyright notice,
00008     this list of conditions and the following disclaimer.
00009 
00010   - Redistributions in binary form must reproduce the above copyright notice,
00011     this list of conditions and the following disclaimer in the documentation and/or
00012     other materials provided with the distribution.
00013 
00014   - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
00015     may be used to endorse or promote products derived from this software without specific
00016     prior written permission.
00017 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00027 */
00028 
00029 #include "StdAfx.h"
00030 #include "CACmdLnOptions.hpp"
00031 #include "CAUtil.hpp"
00032 #include "CAMix.hpp"
00033 #include "CAMsg.hpp"
00034 #include "CASocketAddrINet.hpp"
00035 #include "CASocket.hpp"
00036 #include "CAXMLBI.hpp"
00037 #include "xml/DOM_Output.hpp"
00038 #include "CABase64.hpp"
00039 #include "CADynaNetworking.hpp"
00040 #ifdef PAYMENT
00041 #include "CAAccountingDBInterface.hpp"
00042 #endif
00043 //#ifdef LOG_CRIME
00044   #include "tre/regex.h"
00045 //#endif
00046 
00047 CACmdLnOptions::CACmdLnOptions()
00048   {
00049     m_bDaemon=false;
00050     m_bSyslog=false;
00051     m_bLogConsole = false;
00052     m_bSocksSupport = false;
00053     m_bLocalProxy=m_bFirstMix=m_bLastMix=m_bMiddleMix=false;
00054 #ifndef ONLY_LOCAL_PROXY
00055     m_bIsRunReConfigure=false;
00056     m_addrInfoServices = NULL;
00057     m_addrInfoServicesSize=0;
00058     m_pcsReConfigure=new CAMutex();
00059     //m_pSignKey=NULL;
00060     //m_pOwnCertificate=NULL;
00061     m_OpCert=NULL;
00062     m_pMultiSignature=NULL;
00063     m_pPrevMixCertificate=NULL;
00064     m_pNextMixCertificate=NULL;
00065     m_pTrustedRootCertificates=NULL;
00066     m_bVerifyMixCerts=false;
00067     m_bCompressedLogs=false;
00068     m_pLogEncryptionCertificate=NULL;
00069     m_bIsEncryptedLogEnabled=false;
00070     m_docMixInfo= createDOMDocument();
00071     m_docMixXml=NULL;
00072     m_pCascadeXML=NULL;
00073     m_docOpTnCs=NULL; //Operator Terms and Conditions (if any)
00074     m_bAcceptReconfiguration=false;
00075     m_maxNrOfUsers = 0;
00076 #ifdef COUNTRY_STATS
00077     m_dbCountryStatsHost=m_dbCountryStatsPasswd=m_dbCountryStatsUser=NULL;
00078 #endif
00079 #endif //ONLY_LOCAL_PROXY
00080     m_iTargetPort=m_iSOCKSPort=m_iSOCKSServerPort=0xFFFF;
00081     m_strTargetHost=m_strSOCKSHost=NULL;
00082     m_strUser=NULL;
00083     m_strCascadeName=NULL;
00084     m_strLogDir=NULL;
00085     setZero64(m_maxLogFileSize);
00086     m_strEncryptedLogDir=NULL;
00087     m_arTargetInterfaces=NULL;
00088     m_cnTargets=0;
00089     m_arListenerInterfaces=NULL;
00090     m_cnListenerInterfaces=0;
00091     m_arStrVisibleAddresses=NULL;
00092     m_cnVisibleAddresses=0;
00093     m_nrOfOpenFiles=-1;
00094     m_strMixID=NULL;
00095     m_strMixName=NULL;
00096     m_bAutoReconnect=false;
00097     m_strConfigFile=NULL;
00098     m_strPidFile=NULL;
00099 #ifdef PAYMENT
00100     m_pBI=NULL;
00101     m_strDatabaseHost=NULL;
00102     m_strDatabaseName=NULL;
00103     m_strDatabaseUser=NULL;
00104     m_strDatabasePassword=NULL;
00105     m_strAiID=NULL;
00106 #endif
00107 #ifdef SERVER_MONITORING
00108     m_strMonitoringListenerHost = NULL;
00109     m_iMonitoringListenerPort = 0xFFFF;
00110 #endif
00111     m_termsAndConditionsTemplates = NULL;
00112     m_nrOfTermsAndConditionsTemplates = 0;
00113 
00114 #ifdef LOG_CRIME
00115     m_logPayload = false;
00116     m_arCrimeRegExpsURL=NULL;
00117     m_nCrimeRegExpsURL=0;
00118     m_arCrimeRegExpsPayload=NULL;
00119     m_nCrimeRegExpsPayload=0;
00120     m_nrOfSurveillanceIPs = 0;
00121     m_surveillanceIPs = NULL;
00122     m_nrOfSurveillanceAccounts = 0;
00123     m_surveillanceAccounts = NULL;
00124 #endif
00125 
00126 #ifdef DATA_RETENTION_LOG
00127     m_strDataRetentionLogDir=NULL;
00128 #endif
00129 
00130 #ifdef DYNAMIC_MIX
00131     m_strLastCascadeProposal = NULL;
00132 #endif
00133 
00134 #if defined(DELAY_CHANNELS) && defined(DELAY_USERS)
00135     if(isFirstMix())
00136     {
00137       m_u32DelayChannelUnlimitTraffic=DELAY_USERS_TRAFFIC;
00138       m_u32DelayChannelBucketGrow=DELAY_USERS_BUCKET_GROW;
00139       m_u32DelayChannelBucketGrowIntervall=DELAY_USERS_BUCKET_GROW_INTERVALL;
00140     }
00141     else
00142     {
00143       m_u32DelayChannelUnlimitTraffic=DELAY_CHANNEL_TRAFFIC;
00144       m_u32DelayChannelBucketGrow=DELAY_BUCKET_GROW;
00145       m_u32DelayChannelBucketGrowIntervall=DELAY_BUCKET_GROW_INTERVALL;
00146     }
00147 #elif defined(DELAY_CHANNELS)
00148     m_u32DelayChannelUnlimitTraffic=DELAY_CHANNEL_TRAFFIC;
00149     m_u32DelayChannelBucketGrow=DELAY_BUCKET_GROW;
00150     m_u32DelayChannelBucketGrowIntervall=DELAY_BUCKET_GROW_INTERVALL;
00151 #elif defined (DELAY_USERS)
00152     m_u32DelayChannelUnlimitTraffic=DELAY_USERS_TRAFFIC;
00153     m_u32DelayChannelBucketGrow=DELAY_USERS_BUCKET_GROW;
00154     m_u32DelayChannelBucketGrowIntervall=DELAY_USERS_BUCKET_GROW_INTERVALL;
00155 #endif
00156 
00157 #if defined(DELAY_CHANNELS_LATENCY)
00158     m_u32DelayChannelLatency = DELAY_CHANNEL_LATENCY;
00159 #endif
00160 
00161     /* initialize pointer to option setter functions */
00162     initMainOptionSetters();
00163     initGeneralOptionSetters();
00164     initCertificateOptionSetters();
00165     initAccountingOptionSetters();
00166     initNetworkOptionSetters();
00167     initTermsAndConditionsOptionSetters();
00168     initCrimeDetectionOptionSetters();
00169  }
00170 
00171 CACmdLnOptions::~CACmdLnOptions()
00172   {
00173     cleanup();
00174   }
00175 
00176 void CACmdLnOptions::initMainOptionSetters()
00177 {
00178   mainOptionSetters = new optionSetter_pt[MAIN_OPTION_SETTERS_NR];
00179   int count = -1;
00180 
00181   mainOptionSetters[++count]=
00182     &CACmdLnOptions::setGeneralOptions;
00183   mainOptionSetters[++count]=
00184     &CACmdLnOptions::setMixDescription;
00185   mainOptionSetters[++count]=
00186     &CACmdLnOptions::setCertificateOptions;
00187   mainOptionSetters[++count]=
00188     &CACmdLnOptions::setAccountingOptions;
00189   mainOptionSetters[++count]=
00190     &CACmdLnOptions::setNetworkOptions;
00191   mainOptionSetters[++count]=
00192     &CACmdLnOptions::setRessourceOptions;
00193   mainOptionSetters[++count]=
00194     &CACmdLnOptions::setTermsAndConditions;
00195   mainOptionSetters[++count]=
00196     &CACmdLnOptions::setCrimeDetectionOptions;
00197 }
00198 
00199 void CACmdLnOptions::initGeneralOptionSetters()
00200 {
00201   generalOptionSetters = new optionSetter_pt[GENERAL_OPTIONS_NR];
00202   int count = -1;
00203 
00204   generalOptionSetters[++count]=
00205     &CACmdLnOptions::setDaemonMode;
00206   generalOptionSetters[++count]=
00207     &CACmdLnOptions::setNrOfFileDescriptors;    
00208   generalOptionSetters[++count]=
00209     &CACmdLnOptions::setUserID;
00210   generalOptionSetters[++count]=
00211     &CACmdLnOptions::setLoggingOptions;
00212   generalOptionSetters[++count]=
00213     &CACmdLnOptions::setMixType;
00214   generalOptionSetters[++count]=
00215     &CACmdLnOptions::setMixName;
00216   generalOptionSetters[++count]=
00217     &CACmdLnOptions::setMixID;
00218   generalOptionSetters[++count]=
00219     &CACmdLnOptions::setDynamicMix;
00220   generalOptionSetters[++count]=
00221     &CACmdLnOptions::setMinCascadeLength;
00222   generalOptionSetters[++count]=
00223     &CACmdLnOptions::setCascadeNameFromOptions;
00224 
00225   generalOptionSetters[++count]=
00226     &CACmdLnOptions::setMaxUsers;
00227 }
00228 
00229 void CACmdLnOptions::initCertificateOptionSetters()
00230 {
00231   certificateOptionSetters = new optionSetter_pt[MAX_CERTIFICATE_OPTIONS_NR];
00232   m_nCertificateOptionsSetters = 0;
00233 
00234   certificateOptionSetters[m_nCertificateOptionsSetters++]=&CACmdLnOptions::setOwnOperatorCertificate;
00235   certificateOptionSetters[m_nCertificateOptionsSetters++]=&CACmdLnOptions::setOwnCertificate;
00236   certificateOptionSetters[m_nCertificateOptionsSetters++]=&CACmdLnOptions::setNextMixCertificate;
00237   certificateOptionSetters[m_nCertificateOptionsSetters++]=&CACmdLnOptions::setPrevMixCertificate;
00238 }
00239 
00240 void CACmdLnOptions::initAccountingOptionSetters()
00241 {
00242   accountingOptionSetters = new optionSetter_pt[ACCOUNTING_OPTIONS_NR];
00243   int count = -1;
00244 
00245   accountingOptionSetters[++count]=
00246     &CACmdLnOptions::setPaymentInstance;
00247   accountingOptionSetters[++count]=
00248       &CACmdLnOptions::setPriceCertificate;
00249   accountingOptionSetters[++count]=
00250     &CACmdLnOptions::setAccountingSoftLimit;
00251   accountingOptionSetters[++count]=
00252     &CACmdLnOptions::setAccountingHardLimit;
00253   accountingOptionSetters[++count]=
00254     &CACmdLnOptions::setPrepaidInterval;
00255   accountingOptionSetters[++count]=
00256     &CACmdLnOptions::setSettleInterval;
00257   accountingOptionSetters[++count]=
00258     &CACmdLnOptions::setAccountingDatabase;
00259 }
00260 
00261 void CACmdLnOptions::initNetworkOptionSetters()
00262 {
00263   networkOptionSetters = new optionSetter_pt[NETWORK_OPTIONS_NR];
00264   int count = -1;
00265 
00266   networkOptionSetters[++count]=
00267     &CACmdLnOptions::setInfoServices;
00268   networkOptionSetters[++count]=
00269     &CACmdLnOptions::setListenerInterfaces;
00270   networkOptionSetters[++count]=
00271     &CACmdLnOptions::setTargetInterfaces;
00272   networkOptionSetters[++count]=
00273     &CACmdLnOptions::setServerMonitoring;
00274   networkOptionSetters[++count]=
00275     &CACmdLnOptions::setKeepAliveTraffic;
00276 }
00277 
00278 void CACmdLnOptions::initTermsAndConditionsOptionSetters()
00279 {
00280 
00281   termsAndConditionsOptionSetters = new optionSetter_pt[TERMS_AND_CONDITIONS_OPTIONS_NR];
00282   int count = -1;
00283 
00284   termsAndConditionsOptionSetters[++count]=
00285       &CACmdLnOptions::setTermsAndConditionsTemplates;
00286   termsAndConditionsOptionSetters[++count]=
00287         &CACmdLnOptions::setTermsAndConditionsList;
00288 }
00289 
00290 void CACmdLnOptions::initCrimeDetectionOptionSetters()
00291 {
00292   crimeDetectionOptionSetters = new optionSetter_pt[CRIME_DETECTION_OPTIONS_NR];
00293   int count = -1;
00294 
00295   crimeDetectionOptionSetters[++count]=
00296     &CACmdLnOptions::setCrimeURLRegExp;
00297   crimeDetectionOptionSetters[++count]=
00298     &CACmdLnOptions::setCrimePayloadRegExp;
00299   crimeDetectionOptionSetters[++count]=
00300     &CACmdLnOptions::setCrimeSurveillanceAccounts;
00301   crimeDetectionOptionSetters[++count]=
00302     &CACmdLnOptions::setCrimeSurveillanceIP;
00303 }
00306 SINT32 CACmdLnOptions::cleanup()
00307   {
00308     clean();
00309 #ifndef ONLY_LOCAL_PROXY
00310     delete m_pcsReConfigure;
00311     m_pcsReConfigure=NULL;
00312 #endif
00313     return E_SUCCESS;
00314   }
00315 
00318 SINT32 CACmdLnOptions::clearTargetInterfaces()
00319   {
00320     if(m_arTargetInterfaces!=NULL)
00321       {
00322         for(UINT32 i=0;i<m_cnTargets;i++)
00323         {
00324           delete m_arTargetInterfaces[i].addr;
00325           m_arTargetInterfaces[i].addr = NULL;
00326         }
00327         delete[] m_arTargetInterfaces;
00328         m_arTargetInterfaces = NULL;
00329       }
00330     m_cnTargets=0;
00331     m_arTargetInterfaces=NULL;
00332     return E_SUCCESS;
00333   }
00334 
00337 SINT32 CACmdLnOptions::clearListenerInterfaces()
00338   {
00339     if(m_arListenerInterfaces!=NULL)
00340       {
00341         for(UINT32 i=0;i<m_cnListenerInterfaces;i++)
00342         {
00343           delete m_arListenerInterfaces[i];
00344           m_arListenerInterfaces[i] = NULL;
00345         }
00346         delete[] m_arListenerInterfaces;
00347       }
00348     m_cnListenerInterfaces=0;
00349     m_arListenerInterfaces=NULL;
00350     return E_SUCCESS;
00351   }
00352 
00353 #ifndef ONLY_LOCAL_PROXY
00354 
00356 SINT32 CACmdLnOptions::clearVisibleAddresses()
00357   {
00358     if(m_arStrVisibleAddresses!=NULL)
00359     {
00360       for(UINT32 i=0;i<m_cnVisibleAddresses;i++)
00361       {
00362         delete[] m_arStrVisibleAddresses[i];
00363         m_arStrVisibleAddresses[i] = NULL;
00364       }
00365       delete[] m_arStrVisibleAddresses;
00366     }
00367     m_cnVisibleAddresses=0;
00368     m_arStrVisibleAddresses=NULL;
00369     return E_SUCCESS;
00370   }
00371 
00386 SINT32 CACmdLnOptions::addVisibleAddresses(DOMNode* nodeProxy)
00387   {
00388     if(nodeProxy==NULL) return E_UNKNOWN;
00389     ASSERT_PARENT_NODE_NAME
00390       (nodeProxy->getNodeName(), OPTIONS_NODE_PROXY, OPTIONS_NODE_VISIBLE_ADDRESS_LIST);
00391     DOMNode* elemVisAdresses=NULL;
00392     getDOMChildByName(nodeProxy, OPTIONS_NODE_VISIBLE_ADDRESS_LIST, elemVisAdresses);
00393     DOMNode* elemVisAddress=NULL;
00394     getDOMChildByName(elemVisAdresses, OPTIONS_NODE_VISIBLE_ADDRESS ,elemVisAddress);
00395     while(elemVisAddress!=NULL)
00396       {
00397         if(equals(elemVisAddress->getNodeName(), OPTIONS_NODE_VISIBLE_ADDRESS))
00398           {
00399             DOMElement* elemHost;
00400             if(getDOMChildByName(elemVisAddress, OPTIONS_NODE_HOST ,elemHost)==E_SUCCESS)
00401               {
00402                 UINT8 tmp[TMP_BUFF_SIZE];
00403                 UINT32 len = TMP_BUFF_SIZE;
00404                 if(getDOMElementValue(elemHost,tmp,&len)==E_SUCCESS)
00405                   {//append the new address to the list of addresses
00406                     UINT8** tmpAr=new UINT8*[m_cnVisibleAddresses+1];
00407                     if(m_arStrVisibleAddresses!=NULL)
00408                       {
00409                         memcpy(tmpAr,m_arStrVisibleAddresses,m_cnVisibleAddresses*sizeof(UINT8*));
00410                         delete[] m_arStrVisibleAddresses;
00411                         m_arStrVisibleAddresses = NULL;
00412                       }
00413                     tmpAr[m_cnVisibleAddresses]=new UINT8[len+1];
00414                     memcpy(tmpAr[m_cnVisibleAddresses],tmp,len+1);
00415                     m_cnVisibleAddresses++;
00416                     m_arStrVisibleAddresses=tmpAr;
00417                   }
00418               }
00419           }
00420         elemVisAddress=elemVisAddress->getNextSibling();
00421       }
00422     return E_SUCCESS;
00423   }
00424 
00425 SINT32 CACmdLnOptions::getVisibleAddress(UINT8* strAddressBuff, UINT32 len,UINT32 nr)
00426   {
00427     if(strAddressBuff==NULL||nr==0||nr>m_cnVisibleAddresses)
00428       {
00429         return E_UNKNOWN;
00430       }
00431     if(strlen((char*)m_arStrVisibleAddresses[nr-1]  )>=len)
00432       {
00433         return E_SPACE;
00434       }
00435     strcpy((char*)strAddressBuff,(char*)m_arStrVisibleAddresses[nr-1]);
00436     return E_SUCCESS;
00437   }
00438 #endif //ONLY_LOCAL_PROXY
00439 
00441 void CACmdLnOptions::clean()
00442   {
00443     delete[] m_strConfigFile;
00444     m_strConfigFile=NULL;
00445 
00446     delete[] m_strTargetHost;
00447     m_strTargetHost=NULL;
00448 
00449     delete[] m_strSOCKSHost;
00450     m_strSOCKSHost=NULL;
00451 
00452 #ifndef ONLY_LOCAL_PROXY
00453     if (m_addrInfoServices != NULL)
00454       {
00455         for (UINT32 i = 0; i < m_addrInfoServicesSize; i++)
00456         {
00457           delete m_addrInfoServices[i];
00458           m_addrInfoServices[i] = NULL;
00459         }
00460         delete[] m_addrInfoServices;
00461       m_addrInfoServices=NULL;
00462         m_addrInfoServicesSize = 0;
00463       }
00464 #endif //ONLY_LOCAL_PROXY
00465 
00466 
00467     delete[] m_strCascadeName;
00468     m_strCascadeName=NULL;
00469 
00470     delete[] m_strLogDir;
00471     m_strLogDir=NULL;
00472 
00473     delete[] m_strPidFile;
00474     m_strPidFile=NULL;
00475 
00476     delete[] m_strEncryptedLogDir;
00477     m_strEncryptedLogDir=NULL;
00478 
00479     delete[] m_strUser;
00480     m_strUser=NULL;
00481 
00482     delete[] m_strMixID;
00483     m_strMixID=NULL;
00484 
00485     delete[] m_strMixName;
00486     m_strMixName=NULL;
00487 
00488     clearTargetInterfaces();
00489     clearListenerInterfaces();
00490 #ifndef ONLY_LOCAL_PROXY
00491     if(m_docMixInfo!=NULL)
00492       m_docMixInfo=NULL;
00493     clearVisibleAddresses();
00494 
00495     //delete m_pSignKey;
00496     //m_pSignKey=NULL;
00497 
00498     //delete m_pOwnCertificate;
00499     //m_pOwnCertificate=NULL;
00500 
00501     delete m_pMultiSignature;
00502     m_pMultiSignature = NULL;
00503 
00504     delete m_OpCert;
00505     m_OpCert=NULL;
00506 
00507     delete m_pNextMixCertificate;
00508     m_pNextMixCertificate=NULL;
00509 
00510     delete m_pPrevMixCertificate;
00511     m_pPrevMixCertificate=NULL;
00512 
00513     delete m_pLogEncryptionCertificate;
00514     m_pLogEncryptionCertificate=NULL;
00515 
00516     if(m_docMixInfo!=NULL)
00517     {
00518       m_docMixInfo->release();
00519       m_docMixInfo=NULL;
00520     }
00521 
00522     if(m_docMixXml!=NULL)
00523     {
00524       m_docMixXml->release();
00525       m_docMixXml=NULL;
00526     }
00527 
00528     if(m_docOpTnCs!=NULL)
00529     {
00530       m_docOpTnCs->release();
00531       m_docOpTnCs=NULL;
00532     }
00533 
00534 #ifdef COUNTRY_STATS
00535     delete[] m_dbCountryStatsHost;
00536     m_dbCountryStatsHost = NULL;
00537     delete[] m_dbCountryStatsUser;
00538     m_dbCountryStatsUser = NULL;
00539     delete[] m_dbCountryStatsPasswd;
00540     m_dbCountryStatsPasswd = NULL;
00541 #endif
00542 
00543 #ifdef DATA_RETENTION_LOG
00544     delete[] m_strDataRetentionLogDir;
00545     m_strDataRetentionLogDir=NULL;
00546 #endif
00547 
00548 #endif //ONLY_LOCAL_PROXY
00549 #ifdef SERVER_MONITORING
00550     if(m_strMonitoringListenerHost != NULL)
00551     {
00552       delete[] m_strMonitoringListenerHost;
00553       m_strMonitoringListenerHost = NULL;
00554     }
00555 #endif
00556     delete [] mainOptionSetters;
00557     mainOptionSetters = NULL;
00558     delete [] generalOptionSetters;
00559     generalOptionSetters = NULL;
00560     delete certificateOptionSetters;
00561     certificateOptionSetters = NULL;
00562     delete [] accountingOptionSetters;
00563     accountingOptionSetters = NULL;
00564     delete [] networkOptionSetters;
00565     networkOptionSetters = NULL;
00566 }
00567 
00568 SINT32 CACmdLnOptions::parse(int argc,const char** argv)
00569     {
00570   int iDaemon=0;
00571   char* target=NULL;
00572   int iLocalProxy=0;
00573   int SOCKSport=-1;
00574   char* socks=NULL;
00575   char* logdir=NULL;
00576   int iCompressedLogs=0;
00577   char* serverPort=NULL;
00578   int iVersion=0;
00579   char* configfile=NULL;
00580   int iAutoReconnect=0;
00581   char* strPidFile=NULL;
00582   char* strCreateConf=0;
00583   //DOM_Document docMixXml;
00584   poptOption theOptions[]=
00585    {
00586     {"localproxy",'j',POPT_ARG_NONE,&iLocalProxy,0,"act as local proxy",NULL},
00587     {"daemon",'d',POPT_ARG_NONE,&iDaemon,0,"start as daemon [only for local proxy]",NULL},
00588     {"next",'n',POPT_ARG_STRING,&target,0,"first mix of cascade [only for local proxy]","<ip:port>"},
00589     {"autoreconnect",'a',POPT_ARG_NONE,&iAutoReconnect,0,"auto reconnects if connection to first mix was lost [only for local proxy]",NULL},
00590     {"port",'p',POPT_ARG_STRING,&serverPort,0,"listening on [host:]port|path [only for local proxy]","<[host:]port|path>"},
00591     {"socksport",'s',POPT_ARG_INT,&SOCKSport,0,"listening port for socks","<portnumber>"},
00592     {"logdir",'l',POPT_ARG_STRING,&logdir,0,"directory where log files go to [only for local proxy]","<dir>"},
00593 #ifdef COMPRESSED_LOGS
00594     {"gzip",'z',POPT_ARG_NONE,&iCompressedLogs,0,"create gziped logs",NULL},
00595 #endif
00596     {"config",'c',POPT_ARG_STRING,&configfile,0,"config file to use [for a real Mix in a cascade]","<file>"},
00597     {"version",'v',POPT_ARG_NONE,&iVersion,0,"show version",NULL},
00598     {"pidfile",'r',POPT_ARG_STRING,&strPidFile,0,"file where the PID will be stored","<file>"},
00599     {"createConf",0,POPT_ARG_STRING,&strCreateConf,0,"creates a generic configuration for MixOnCD","[<file>]"},
00600     POPT_AUTOHELP
00601     {NULL,0,0,
00602     NULL,0,NULL,NULL}
00603   };
00604   poptContext ctx=poptGetContext(NULL,argc,argv,theOptions,0);
00605   SINT32 ret=poptGetNextOpt(ctx);
00606   while(ret==POPT_ERROR_BADOPT)
00607     ret=poptGetNextOpt(ctx);
00608   poptFreeContext(ctx);
00609   if(iVersion!=0)
00610     {
00611       printf(MIX_VERSION_INFO);
00612       for(UINT32 t=0;t<10000;t++)
00613         {
00614           CASocket* pSocket=new CASocket;
00615           if(pSocket->create(false)!=E_SUCCESS)
00616             {
00617               printf("Max open sockets: %u\n",t);
00618               exit(0);
00619             }
00620         }
00621       printf("Max open sockets: >10000\n");
00622       exit(0);
00623     }
00624     
00625     if (MIX_VERSION_TESTING)
00626     {
00627       CAMsg::printMsg(LOG_WARNING, MIX_VERSION_TESTING_TEXT);
00628     }
00629     
00630 #ifndef ONLY_LOCAL_PROXY
00631   if(strCreateConf!=NULL)
00632     {
00633       createMixOnCDConfiguration((UINT8*)strCreateConf);
00634       exit(0);
00635     }
00636 #endif
00637   if(iLocalProxy!=0)
00638     m_bLocalProxy=true;
00639   if(m_bLocalProxy&&iAutoReconnect!=0)
00640     m_bAutoReconnect=true;
00641 
00642     /* LERNGRUPPE: Also try to use default config file for Mix Category 1 */
00643     if(configfile == NULL)
00644     {
00645         configfile = (char*) malloc(sizeof(char) * (strlen(DEFAULT_CONFIG_FILE)+1));
00646         strncpy(configfile, DEFAULT_CONFIG_FILE, (strlen(DEFAULT_CONFIG_FILE)+1));
00647 
00648 #if defined (_WIN32) &&!defined(__CYGWIN__)
00649 // R_OK is not defined in Windows POSIX implementation
00650 #define R_OK 4
00651 #endif
00652 
00653         int err = access(configfile, R_OK);
00654         if( err )
00655         {
00656             if(configfile != NULL)
00657             {
00658                 free(configfile);
00659                 configfile = NULL;
00660             }
00661         }
00662     }
00663     /* END LERNGRUPPE */
00664 
00665 
00666   if(configfile!=NULL)
00667     {
00668 #ifndef ONLY_LOCAL_PROXY
00669       ret=readXmlConfiguration(m_docMixXml,(UINT8*)configfile);
00670       if(ret==E_FILE_OPEN)
00671         CAMsg::printMsg(LOG_CRIT,"Could not open config file: %s\n",configfile);
00672       else if(ret==E_FILE_READ)
00673         CAMsg::printMsg(LOG_CRIT,"Could not read config file: %s\n",configfile);
00674       else if(ret==E_XML_PARSE)
00675         CAMsg::printMsg(LOG_CRIT,"Could not parse config file: %s\n",configfile);
00676       else
00677         {
00678           m_strConfigFile=new UINT8[strlen(configfile)+1];
00679           memcpy(m_strConfigFile,configfile,strlen(configfile)+1);
00680         }
00681 #endif
00682       free(configfile);
00683     }
00684   if(iDaemon!=0)
00685       m_bDaemon=true;
00686   if(target!=NULL)
00687       {
00688         if(target[0]=='/') //Unix Domain Sockaet
00689          {
00690           m_strTargetHost=new char[strlen(target)+1];
00691           strcpy(m_strTargetHost,target);
00692          }
00693         else
00694           {
00695             char tmpHostname[TMP_BUFF_SIZE];
00696             SINT32 tmpPort;
00697             char* tmpStr1=strchr(target,':');
00698             if(tmpStr1!=NULL)
00699               {
00700                 memcpy(tmpHostname,target,tmpStr1-target);
00701                 tmpHostname[tmpStr1-target]=0;
00702                 tmpPort=(SINT32)atol(tmpStr1+1);
00703               }
00704             else
00705               {//TODO what if not in right form ?
00706                 //try if it is a number --> use it as port
00707                 //and use 'localhost' as traget-host
00708                 tmpPort=(SINT32)atol(target);
00709                 if(tmpPort!=0) //we get it
00710                   {
00711                     strcpy(tmpHostname,"localhost");
00712                   }
00713                 else //we try to use it as host and use the default port
00714                   {
00715 /* LERNGRUPPE moved the define to CACmdLnOption.hpp because we need it elsewhere too */
00716 //#define DEFAULT_TARGET_PORT 6544
00717                     tmpPort=DEFAULT_TARGET_PORT;
00718                     strcpy(tmpHostname,target);
00719                   }
00720               }
00721             m_strTargetHost=new char[strlen(tmpHostname)+1];
00722             strcpy(m_strTargetHost,tmpHostname);
00723             m_iTargetPort=(UINT16)tmpPort;
00724           }
00725         free(target);
00726       }
00727   if(socks!=NULL)
00728       {
00729         char* tmpStr;
00730         if((tmpStr=strchr(socks,':'))!=NULL)
00731           {
00732             m_strSOCKSHost=new char[tmpStr-socks+1];
00733             (*tmpStr)=0;
00734             strcpy(m_strSOCKSHost,socks);
00735             m_iSOCKSPort=(UINT16)atol(tmpStr+1);
00736           }
00737         free(socks);
00738       }
00739   if(logdir!=NULL)
00740       {
00741           m_strLogDir=new char[strlen(logdir)+1];
00742           strcpy(m_strLogDir,logdir);
00743           free(logdir);
00744       }
00745   if(strPidFile!=NULL)
00746     {
00747       m_strPidFile=new char[strlen(strPidFile)+1];
00748       strcpy(m_strPidFile,strPidFile);
00749       free(strPidFile);
00750     }
00751   if(iCompressedLogs!=0)
00752     m_bCompressedLogs=true;
00753 
00754   if(serverPort!=NULL&&m_bLocalProxy)
00755     {
00756       m_arListenerInterfaces=new CAListenerInterface*[1];
00757       m_arListenerInterfaces[0]=NULL;
00758       m_cnListenerInterfaces=0;
00759       char* tmpStr;
00760       if(serverPort[0]=='/') //Unix Domain Socket
00761         {
00762           m_arListenerInterfaces[0]=CAListenerInterface::getInstance(RAW_UNIX,(UINT8*)serverPort);
00763         }
00764       else //Internet Socket
00765         {
00766           char* strServerHost=NULL;
00767           SINT32 iServerPort;
00768           if((tmpStr=strchr(serverPort,':'))!=NULL) //host:port
00769             {
00770               strServerHost=new char[tmpStr-serverPort+1];
00771               (*tmpStr)=0;
00772               strcpy(strServerHost,serverPort);
00773               iServerPort=(SINT32)atol(tmpStr+1);
00774             }
00775           else //port only ?
00776             {
00777               iServerPort=(SINT32)atol(serverPort);
00778             }
00779             m_arListenerInterfaces[0]=CAListenerInterface::getInstance(RAW_TCP,(UINT8*)strServerHost,(UINT16)iServerPort);
00780           delete [] strServerHost;
00781           strServerHost = NULL;
00782         }
00783       free(serverPort);
00784       if(m_arListenerInterfaces[0]!=0)
00785         m_cnListenerInterfaces=1;
00786     }
00787 
00788   m_iSOCKSServerPort=(UINT16)SOCKSport;
00789 #ifndef ONLY_LOCAL_PROXY
00790   if(!m_bLocalProxy)
00791     {
00792       ret=processXmlConfiguration(m_docMixXml);
00793 #ifndef DYNAMIC_MIX
00794       if(ret!=E_SUCCESS)
00795         return ret;
00796     }
00797 #else
00798     /* LERNGRUPPE: Let's try to recover and build a default configuration */
00799     if(ret!=E_SUCCESS)
00800     {
00801         createDefaultConfiguration();
00802         ret=processXmlConfiguration(m_docMixXml);
00803         if(ret!=E_SUCCESS)
00804             return ret;
00805     }
00806                 }
00807 #endif
00808 
00809     /* Try to read InfoService configuration from  external file infoservices.xml */
00810     XERCES_CPP_NAMESPACE::DOMDocument* infoservices;
00811     if( readXmlConfiguration(infoservices,(UINT8*)"infoservices.xml") == E_SUCCESS )
00812     {
00813       CAMsg::printMsg(LOG_DEBUG, "Will now get InfoServices from infoservices.xml (this overrides the InfoServices from the default config!)\n");
00814       DOMElement* elemIs=infoservices->getDocumentElement();
00815       parseInfoServices(elemIs);
00816     }
00817 
00818 #ifdef DYNAMIC_MIX
00819     /*  Ok, at this point we should make sure that we have a minimal configuration.
00820     If not we try to fill up the missing parameters with default values*/
00821     if( checkCertificates() != E_SUCCESS )
00822     {
00823         CAMsg::printMsg(LOG_CRIT, "I was not able to get a working certificate, please check the configuration! Exiting now\n");
00824         exit(0);
00825     }
00826     UINT32 running = 0;
00827     CAMsg::printMsg( LOG_INFO, "I will now test if I have enough information about InfoServices...\n");
00828     if( checkInfoServices(&running) != E_SUCCESS )
00829     {
00831         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);
00832         exit(0);
00833     }
00834     CAMsg::printMsg( LOG_INFO, "InfoService information ok\n");
00835     if( checkListenerInterfaces() != E_SUCCESS )
00836     {
00837         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");
00838         exit(0);
00839     }
00840     if( checkMixId() != E_SUCCESS)
00841     {
00842         CAMsg::printMsg(LOG_CRIT, "ARGS, I don't have an unique ID, cannot create one! Exiting now\n");
00843         exit(0);
00844     }
00845 #endif // DYNAMIC_MIX
00846 #endif //ONLY_LOCAL_PROXY
00847   return E_SUCCESS;
00848  }
00849 
00850 #ifndef ONLY_LOCAL_PROXY
00851 struct t_CMNDLN_REREAD_PARAMS
00852   {
00853     CACmdLnOptions* pCmdLnOptions;
00854     CAMix* pMix;
00855   };
00856 #endif //ONLY_LOCAL_PROXY
00857 
00865 SINT32 CACmdLnOptions::setNewValues(CACmdLnOptions& newOptions)
00866   {
00867     //Copy Targets
00868     if(newOptions.getTargetInterfaceCount()>0)
00869       {
00870         clearTargetInterfaces();
00871         m_cnTargets=newOptions.getTargetInterfaceCount();
00872         m_arTargetInterfaces=new TargetInterface[m_cnTargets];
00873         for(UINT32 i=0;i<m_cnTargets;i++)
00874           newOptions.getTargetInterface(m_arTargetInterfaces[i],i+1);
00875       }
00876 #if defined( DELAY_CHANNELS)||defined(DELAY_USERS)
00877     //Copy ressources limitation
00878     m_u32DelayChannelUnlimitTraffic=newOptions.getDelayChannelUnlimitTraffic();
00879     m_u32DelayChannelBucketGrow=newOptions.getDelayChannelBucketGrow();
00880     m_u32DelayChannelBucketGrowIntervall=newOptions.getDelayChannelBucketGrowIntervall();
00881 #endif
00882 #if defined( DELAY_CHANNELS_LATENCY)
00883     //Copy ressources limitation
00884     m_u32DelayChannelLatency=newOptions.getDelayChannelLatency();
00885 #endif
00886     if(newOptions.getMaxNrOfUsers()>0)
00887       m_maxNrOfUsers=newOptions.getMaxNrOfUsers();
00888     return E_SUCCESS;
00889 }
00890 
00891 #ifndef ONLY_LOCAL_PROXY
00892 
00897 #ifndef DYNAMIC_MIX
00898 SINT32 CACmdLnOptions::setNextMix(XERCES_CPP_NAMESPACE::DOMDocument* doc)
00899   {
00900     CAMsg::printMsg(LOG_DEBUG,"setNextMix() - start\n");
00901     DOMElement* elemRoot = doc->getDocumentElement();
00902 
00903     //getCertificates if given...
00904     DOMElement* elemSig;
00905     getDOMChildByName(elemRoot, OPTIONS_NODE_SIGNATURE, elemSig, false);
00906     //Own Certiticate first
00907     //nextMixCertificate if given
00908     DOMElement* elemCert;
00909     getDOMChildByName(elemSig, OPTIONS_NODE_X509DATA, elemCert,true);
00910     if(elemSig!=NULL)
00911         m_pNextMixCertificate = CACertificate::decode(elemCert->getFirstChild(),CERT_X509CERTIFICATE);
00912 
00913     DOMElement* elemOptionsRoot = m_docMixXml->getDocumentElement();
00914     DOMElement* elemOptionsCerts;
00915     getDOMChildByName(elemOptionsRoot, OPTIONS_NODE_CERTIFICATE_LIST, elemOptionsCerts, false);
00916     DOMElement* elemOptionsNextMixCert;
00917 
00918     if(getDOMChildByName(elemOptionsRoot, OPTIONS_NODE_NEXT_MIX_CERTIFICATE, elemOptionsNextMixCert, false) != E_SUCCESS)
00919     {
00920         elemOptionsNextMixCert = createDOMElement(m_docMixXml, OPTIONS_NODE_NEXT_MIX_CERTIFICATE);
00921         elemOptionsCerts->appendChild(elemOptionsNextMixCert);
00922         elemOptionsNextMixCert->appendChild(m_docMixXml->importNode(elemCert->getFirstChild(),true));
00923     }
00924     else
00925     {
00926         if(elemOptionsNextMixCert->hasChildNodes())
00927         {
00928             elemOptionsNextMixCert->replaceChild(m_docMixXml->importNode(elemCert->getFirstChild(),true),
00929                     elemOptionsNextMixCert->getFirstChild());
00930         }
00931         else
00932         {
00933             elemOptionsNextMixCert->appendChild(m_docMixXml->importNode(elemCert->getFirstChild(),true));
00934         }
00935     }
00936     CAMsg::printMsg(LOG_DEBUG,"setNextMix() - certificates done\n");
00937     DOMElement* elemNextMix;
00938     getDOMChildByName(elemRoot, OPTIONS_NODE_LISTENER_INTERFACE, elemNextMix,true);
00939 
00940     DOMElement* elemOptionsNetwork;
00941     DOMElement* elemOptionsNextMixInterface;
00942 
00943     if(getDOMChildByName(elemOptionsRoot, OPTIONS_NODE_NETWORK, elemOptionsNetwork, false) != E_SUCCESS)
00944     {
00945         elemOptionsNetwork = createDOMElement(m_docMixXml, OPTIONS_NODE_NETWORK);
00946         elemOptionsRoot->appendChild(elemOptionsNetwork);
00947     }
00948 
00949     if(getDOMChildByName(elemOptionsNetwork, OPTIONS_NODE_NEXT_MIX, elemOptionsNextMixInterface, false) != E_SUCCESS)
00950     {
00951         elemOptionsNextMixInterface = createDOMElement(m_docMixXml, OPTIONS_NODE_NEXT_MIX);
00952         elemOptionsNetwork->appendChild(elemOptionsNextMixInterface);
00953     }
00954     else
00955     {
00956         while(elemOptionsNextMixInterface->hasChildNodes())
00957         {
00958             elemOptionsNextMixInterface->removeChild(elemOptionsNextMixInterface->getFirstChild());
00959         }
00960     }
00961 
00962     DOMNode* interfaceData = elemNextMix->getFirstChild();
00963     while(interfaceData != NULL)
00964     {
00965         elemOptionsNextMixInterface->appendChild(m_docMixXml->importNode(interfaceData,true));
00966         interfaceData = interfaceData->getNextSibling();
00967     }
00968 
00969     CAMsg::printMsg(LOG_DEBUG,"setNextMix() - end\n");
00970     return processXmlConfiguration(m_docMixXml);
00971 }
00972 
00973 #else //DYNAMIC_MIX
00974 
00975 SINT32 CACmdLnOptions::setNextMix(DOM_Document& doc)
00976 {
00977   resetNextMix();
00979   DOM_Element elemRoot = doc.getDocumentElement();
00980   //getCertificates if given...
00981   DOM_Element elemSig;
00982   getDOMChildByName(elemRoot,(UINT8*) OPTIONS_NODE_SIGNATURE, elemSig, false);
00983   DOM_Element elemCert;
00984   getDOMChildByName(elemSig,(UINT8*) OPTIONS_NODE_X509DATA, elemCert, true);
00985   if(elemCert!=NULL)
00986     m_pNextMixCertificate = CACertificate::decode(elemCert.getFirstChild(),CERT_X509CERTIFICATE);
00988   DOM_Node elemNextMix;
00989   DOM_Element elemListeners;
00990   // Search through the ListenerInterfaces an use a non-hidden one!
00991   getDOMChildByName(elemRoot,(UINT8*) OPTIONS_NODE_LISTENER_INTERFACE_LIST, elemListeners, true);
00992   DOM_NodeList nlListenerInterfaces = elemListeners.getElementsByTagName(CAListenerInterface::XML_ELEMENT_NAME);
00993   UINT32 len = nlListenerInterfaces.getLength();
00994   bool foundNonHiddenInterface = false;
00995   for(UINT32 i=0;i<len;i++)
00996   {
00997     elemNextMix=nlListenerInterfaces.item(i);
00998     SINT32 ret = E_SUCCESS;
00999     ret = getDOMElementAttribute(elemNextMix,"hidden",foundNonHiddenInterface);
01000     // Interface was not hidden or "hidden"-Attribute was not specified
01001     if(foundNonHiddenInterface || ret == E_UNSPECIFIED)
01002     {
01003       foundNonHiddenInterface = true;
01004       break;
01005     }
01006   }
01007   if(!foundNonHiddenInterface)
01008   {
01009     CAMsg::printMsg(LOG_ERR, "NEXT MIX HAS NO REAL LISTENERINTERFACES!\n");
01010     exit(0);
01011     return E_UNKNOWN;
01012   }
01014   clearTargetInterfaces();
01015   //get TargetInterfaces
01016   m_cnTargets=0;
01017   TargetInterface* targetInterfaceNextMix=NULL;
01018   if(elemNextMix!=NULL)
01019 {
01020   NetworkType type;
01021   CASocketAddr* addr=NULL;
01022   DOM_Element elemType;
01023   getDOMChildByName(elemNextMix,(UINT8*) OPTIONS_NODE_NETWORK, elemType, false);
01024   UINT8 tmpBuff[TMP_BUFF_SIZE];
01025   UINT32 tmpLen = TMP_BUFF_SIZE;
01026   if(getDOMElementValue(elemType,tmpBuff,&tmpLen)!=E_SUCCESS)
01027     goto SKIP_NEXT_MIX;
01028   strtrim(tmpBuff);
01029   if(strcmp((char*)tmpBuff,"RAW/TCP")==0)
01030     type=RAW_TCP;
01031   else if(strcmp((char*)tmpBuff,"RAW/UNIX")==0)
01032     type=RAW_UNIX;
01033   else if(strcmp((char*)tmpBuff,"SSL/TCP")==0)
01034     type=SSL_TCP;
01035   else if(strcmp((char*)tmpBuff,"SSL/UNIX")==0)
01036     type=SSL_UNIX;
01037   else
01038     goto SKIP_NEXT_MIX;
01039   if(type==SSL_TCP||type==RAW_TCP)
01040   {
01041     DOM_Element elemPort;
01042     DOM_Element elemHost;
01043     DOM_Element elemIP;
01044     UINT8 buffHost[255];
01045     UINT32 buffHostLen=255;
01046     UINT16 port;
01047     getDOMChildByName(elemNextMix,(UINT8*) OPTIONS_NODE_PORT, elemPort, false);
01048     if(getDOMElementValue(elemPort,&port)!=E_SUCCESS)
01049       goto SKIP_NEXT_MIX;
01050     addr=new CASocketAddrINet;
01051     bool bAddrIsSet=false;
01052     getDOMChildByName(elemNextMix,(UINT8*) OPTIONS_NODE_HOST, elemHost, false);
01053       /* The rules for <Host> and <IP> are as follows:
01054     * 1. if <Host> is given and not empty take the <Host> value for the address of the next mix; if not go to 2
01055     * 2. if <IP> if given and not empty take <IP> value for the address of the next mix; if not goto 3.
01056       * 3. this entry for the next mix is invalid!*/
01057     if(elemHost!=NULL)
01058     {
01059       if(getDOMElementValue(elemHost,buffHost,&buffHostLen)==E_SUCCESS&&((CASocketAddrINet*)addr)->setAddr(buffHost,port)==E_SUCCESS)
01060       {
01061         bAddrIsSet=true;
01062       }
01063     }
01064     if(!bAddrIsSet)//now try <IP>
01065     {
01066       getDOMChildByName(elemNextMix,(UINT8*) OPTIONS_NODE_IP, elemIP, false);
01067       if(elemIP == NULL || getDOMElementValue(elemIP,buffHost,&buffHostLen)!=E_SUCCESS)
01068         goto SKIP_NEXT_MIX;
01069       if(((CASocketAddrINet*)addr)->setAddr(buffHost,port)!=E_SUCCESS)
01070         goto SKIP_NEXT_MIX;
01071     }
01072     CAMsg::printMsg(LOG_INFO, "Setting target interface: %s:%d\n", buffHost, port);
01073   }
01074   else
01075 #ifdef HAVE_UNIX_DOMAIN_PROTOCOL
01076 
01077   {
01078     DOM_Element elemFile;
01079     getDOMChildByName(elemNextMix,(UINT8*) OPTIONS_NODE_FILE, elemFile, false);
01080     tmpLen=255;
01081     if(getDOMElementValue(elemFile,tmpBuff,&tmpLen)!=E_SUCCESS)
01082       goto SKIP_NEXT_MIX;
01083     tmpBuff[tmpLen]=0;
01084     strtrim(tmpBuff);
01085     addr=new CASocketAddrUnix;
01086     if(((CASocketAddrUnix*)addr)->setPath((char*)tmpBuff)!=E_SUCCESS)
01087       goto SKIP_NEXT_MIX;
01088   }
01089 #else
01090       goto SKIP_NEXT_MIX;
01091 #endif
01092     targetInterfaceNextMix=new TargetInterface;
01093     targetInterfaceNextMix->target_type=TARGET_MIX;
01094     targetInterfaceNextMix->net_type=type;
01095     targetInterfaceNextMix->addr=addr->clone();
01096     m_cnTargets=1;
01097     if(targetInterfaceNextMix!=NULL)
01098     {
01099       if(m_arTargetInterfaces==NULL)
01100       {
01101         m_cnTargets=0;
01102         m_arTargetInterfaces=new TargetInterface[1];
01103       }
01104       m_arTargetInterfaces[m_cnTargets].net_type=targetInterfaceNextMix->net_type;
01105       m_arTargetInterfaces[m_cnTargets].target_type=targetInterfaceNextMix->target_type;
01106       m_arTargetInterfaces[m_cnTargets++].addr=targetInterfaceNextMix->addr;
01107       delete targetInterfaceNextMix;
01108       targetInterfaceNextMix = NULL;
01109     }
01110 
01111   SKIP_NEXT_MIX:
01112       delete addr;
01113       addr = NULL;
01114 }
01115 
01116   CAMsg::printMsg(LOG_DEBUG,"setNextMix() - end\n");
01117   return E_SUCCESS;
01118 }
01119 #endif //DYNAMIC_MIX
01120 
01121 #endif //ONLY_LOCAL_PROXY
01122 
01123 #ifndef ONLY_LOCAL_PROXY
01124 
01129 #ifndef DYNAMIC_MIX
01130 SINT32 CACmdLnOptions::setPrevMix(XERCES_CPP_NAMESPACE::DOMDocument* doc)
01131 {
01132     CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - start\n");
01133     DOMElement* elemRoot = doc->getDocumentElement();
01134 
01135     //getCertificates if given...
01136     DOMElement* elemSig;
01137     getDOMChildByName(elemRoot, OPTIONS_NODE_SIGNATURE, elemSig, false);
01138     //Own Certiticate first
01139     //nextMixCertificate if given
01140     DOMElement* elemCert;
01141     getDOMChildByName(elemSig, OPTIONS_NODE_X509DATA, elemCert, true);
01142     if(elemCert!=NULL)
01143       {
01144         CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - elem cert found in data from infoservice\n");
01145         DOMElement* elemOptionsRoot = m_docMixXml->getDocumentElement();
01146         CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - got  current options root element\n");
01147         DOMElement* elemOptionsCerts;
01148         getDOMChildByName
01149           (elemOptionsRoot, OPTIONS_NODE_CERTIFICATE_LIST, elemOptionsCerts, false);
01150         DOMElement* elemOptionsPrevMixCert;
01151 
01152         if(getDOMChildByName
01153             (elemOptionsRoot,OPTIONS_NODE_PREV_MIX_CERTIFICATE, elemOptionsPrevMixCert, false) != E_SUCCESS)
01154           {
01155             CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - no prev cert set at the moment\n");
01156             elemOptionsPrevMixCert =createDOMElement( m_docMixXml,"PrevMixCertificate");
01157             elemOptionsCerts->appendChild(elemOptionsPrevMixCert);
01158             CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - try to import the one we got from infoservice\n");
01159             getDOMChildByName
01160               (elemCert, OPTIONS_NODE_X509_CERTIFICATE, elemCert, false);
01161 
01162             CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - Cert to be imported:\n");
01163             UINT8 buff[8192];
01164             UINT32 len=8192;
01165             DOM_Output::dumpToMem(elemCert,buff,&len);
01166             CAMsg::printMsg(LOG_DEBUG,(char*)buff);
01167 
01168             elemOptionsPrevMixCert->appendChild(m_docMixXml->importNode(elemCert,true));
01169             CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - MixConf now:\n");
01170             len=8192;
01171             DOM_Output::dumpToMem(m_docMixXml,buff,&len);
01172             buff[len]=0;
01173             CAMsg::printMsg(LOG_DEBUG,(char*)buff);
01174           }
01175         else
01176         {
01177             if(elemOptionsPrevMixCert->hasChildNodes())
01178             {
01179                 elemOptionsPrevMixCert->replaceChild(m_docMixXml->importNode(elemCert->getFirstChild(),true),
01180                         elemOptionsPrevMixCert->getFirstChild());
01181             }
01182             else
01183             {
01184                 elemOptionsPrevMixCert->appendChild(m_docMixXml->importNode(elemCert->getFirstChild(),true));
01185             }
01186         }
01187       CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - end\n");
01188       return processXmlConfiguration(m_docMixXml);
01189     }
01190     CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - end with error\n");
01191     return E_UNKNOWN;
01192 }
01193 
01194 #else //DYNAMIC_MIX
01195 
01196 SINT32 CACmdLnOptions::setPrevMix(DOM_Document& doc)
01197 {
01198   resetPrevMix();
01199   CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - start\n");
01200   DOM_Element elemRoot = doc.getDocumentElement();
01201   DOM_Element elemSig;
01202   getDOMChildByName(elemRoot,(UINT8*) OPTIONS_NODE_SIGNATURE, elemSig, false);
01203   DOM_Element elemCert;
01204   getDOMChildByName(elemSig,(UINT8*) OPTIONS_NODE_X509DATA, elemCert,true);
01205 
01206   if(elemCert!=NULL)
01207   {
01208     m_pPrevMixCertificate=CACertificate::decode(elemCert.getFirstChild(),CERT_X509CERTIFICATE);
01209     return E_SUCCESS; //processXmlConfiguration(m_docMixXml);
01210   }
01211   CAMsg::printMsg(LOG_DEBUG,"setPrevMix() - end with error\n");
01212   return E_UNKNOWN;
01213 }
01214 #endif //DYNAMIC_MIX
01215 #endif //ONLY_LOCAL_PROXY
01216 
01217 #ifndef ONLY_LOCAL_PROXY
01218 #ifdef DYNAMIC_MIX
01219 SINT32 CACmdLnOptions::resetNextMix()
01220 {
01221   if(m_pNextMixCertificate != NULL)
01222   {
01223     delete m_pNextMixCertificate;
01224     m_pNextMixCertificate = NULL;
01225   }
01226   DOM_Element elemOptionsRoot = m_docMixXml.getDocumentElement();
01227   DOM_Element elemOptionsCerts;
01228   getDOMChildByName(elemOptionsRoot, (UINT8*) OPTIONS_NODE_CERTIFICATE_LIST, elemOptionsCerts, false);
01229   DOM_Element elemTmp;
01230   // Remove existing certificates
01231   if(getDOMChildByName(elemOptionsCerts, (UINT8*) OPTIONS_NODE_PREV_MIX_CERTIFICATE, elemTmp, false) == E_SUCCESS)
01232   {
01233 
01234     elemOptionsCerts.removeChild(elemTmp);
01235   }
01236   if(getDOMChildByName(elemOptionsCerts, (UINT8*) OPTIONS_NODE_PREV_OPERATOR_CERTIFICATE, elemTmp, false) == E_SUCCESS)
01237   {
01238 
01239     elemOptionsCerts.removeChild(elemTmp);
01240   }
01241   clearTargetInterfaces();
01242   return E_SUCCESS;
01243 }
01244 
01245 SINT32 CACmdLnOptions::resetPrevMix()
01246 {
01247   if(m_pPrevMixCertificate != NULL)
01248   {
01249     delete m_pPrevMixCertificate;
01250     m_pPrevMixCertificate = NULL;
01251   }
01252   DOM_Element elemOptionsRoot = m_docMixXml.getDocumentElement();
01253   DOM_Element elemOptionsCerts;
01254   getDOMChildByName(elemOptionsRoot, (UINT8*) OPTIONS_NODE_CERTIFICATE_LIST, elemOptionsCerts, false);
01255   DOM_Element elemTmp;
01256   // Remove existing certificates
01257   if(getDOMChildByName(elemOptionsCerts, (UINT8*) OPTIONS_NODE_NEXT_MIX_CERTIFICATE, elemTmp, false) == E_SUCCESS)
01258   {
01259 
01260     elemOptionsCerts.removeChild(elemTmp);
01261   }
01262   if(getDOMChildByName(elemOptionsCerts, (UINT8*) OPTIONS_NODE_NEXT_OPERATOR_CERTIFICATE, elemTmp, false) == E_SUCCESS)
01263   {
01264 
01265     elemOptionsCerts.removeChild(elemTmp);
01266   }
01267   return E_SUCCESS;
01268 
01269 }
01270 #endif //DYNAMIC_MIX
01271 #endif //ONLY_LOCAL_PROXY
01272 
01273 #ifndef ONLY_LOCAL_PROXY
01274 
01281 SINT32 CACmdLnOptions::reread(CAMix* pMix)
01282   {
01283     if(m_bIsRunReConfigure)
01284       return E_UNKNOWN;
01285     m_bIsRunReConfigure=true;
01286     m_threadReConfigure.setMainLoop(threadReConfigure);
01287     t_CMNDLN_REREAD_PARAMS* param=new t_CMNDLN_REREAD_PARAMS;
01288     param->pCmdLnOptions=this;
01289     param->pMix=pMix;
01290     m_threadReConfigure.start(param,true,false);
01291     return E_SUCCESS;
01292   }
01293 
01298 THREAD_RETURN threadReConfigure(void *param)
01299   {
01300     CACmdLnOptions* pOptions=((t_CMNDLN_REREAD_PARAMS*)param)->pCmdLnOptions;
01301     CAMix* pMix=((t_CMNDLN_REREAD_PARAMS*)param)->pMix;
01302     //pOptions->m_pcsReConfigure->lock();
01303     CAMsg::printMsg(LOG_DEBUG,"ReConfiguration of the Mix is under way....\n");
01304     CACmdLnOptions otmpOptions;
01305     XERCES_CPP_NAMESPACE::DOMDocument* docConfig=NULL;
01306     if(otmpOptions.readXmlConfiguration(docConfig,pOptions->m_strConfigFile)!=E_SUCCESS)
01307       {
01308         CAMsg::printMsg(LOG_DEBUG,"Could not re-read the config file!\n");
01309         goto REREAD_FINISH;
01310       }
01311     CAMsg::printMsg(LOG_DEBUG,"Re-readed config file -- start processing config file!\n");
01312     if(otmpOptions.processXmlConfiguration(docConfig)!=E_SUCCESS)
01313       {
01314         CAMsg::printMsg(LOG_DEBUG,"Re-readed config file -- could not process configuration!\n");
01315         goto REREAD_FINISH;
01316       }
01317     pOptions->setNewValues(otmpOptions);
01318     if(pMix!=NULL)
01319       pMix->reconfigure();
01320 
01321 REREAD_FINISH:
01322     CAMsg::printMsg(LOG_DEBUG,"ReConfiguration of the Mix finished!\n");
01323     //pOptions->m_pcsReConfigure->unlock();
01324     pOptions->m_bIsRunReConfigure=false;
01325     THREAD_RETURN_SUCCESS;
01326   }
01327 #endif //ONLY_LOCAL_PROXY
01328 
01329 bool CACmdLnOptions::getDaemon()
01330   {
01331     return m_bDaemon;
01332   }
01333 
01334 SINT32 CACmdLnOptions::getMixId(UINT8* id,UINT32 len)
01335   {
01336     if(len<24||m_strMixID==NULL) //we need 24 chars (including final \0)
01337       return E_UNKNOWN;
01338     strcpy((char*)id,m_strMixID);
01339     return E_SUCCESS;
01340   }
01341 
01342 
01343 UINT16 CACmdLnOptions::getSOCKSServerPort()
01344   {
01345     return m_iSOCKSServerPort;
01346   }
01347 
01348 UINT16 CACmdLnOptions::getMixPort()
01349   {
01350     return m_iTargetPort;
01351   }
01352 
01353 
01354 SINT32 CACmdLnOptions::getMixHost(UINT8* host,UINT32 len)
01355   {
01356     if(m_strTargetHost==NULL)
01357         return E_UNKNOWN;
01358     if(len<=(UINT32)strlen(m_strTargetHost))
01359         {
01360           return E_UNKNOWN;
01361         }
01362     strcpy((char*)host,m_strTargetHost);
01363     return E_SUCCESS;
01364   }
01365 
01366 #ifndef ONLY_LOCAL_PROXY
01367 UINT16 CACmdLnOptions::getSOCKSPort()
01368   {
01369     return m_iSOCKSPort;
01370   }
01371 
01372 SINT32 CACmdLnOptions::getSOCKSHost(UINT8* host,UINT32 len)
01373   {
01374     if(m_strSOCKSHost==NULL)
01375         return E_UNKNOWN;
01376     if(len<=(UINT32)strlen(m_strSOCKSHost))
01377         {
01378           return E_UNKNOWN;
01379         }
01380     strcpy((char*)host,m_strSOCKSHost);
01381     return (SINT32)strlen(m_strSOCKSHost);
01382   }
01383 #endif //ONLY_LOCAL_PROXY
01384 
01385 #ifdef PAYMENT
01386 
01391 CAXMLBI* CACmdLnOptions::getBI()
01392   {
01393     return m_pBI;
01394   }
01395 
01396 SINT32 CACmdLnOptions::getDatabaseHost(UINT8 * host, UINT32 len)
01397   {
01398     if(m_strDatabaseHost==NULL)
01399       return E_UNKNOWN;
01400     if(len<=(UINT32)strlen((char *)m_strDatabaseHost))
01401       {
01402         return E_UNKNOWN;
01403       }
01404     strcpy((char*)host,(char *)m_strDatabaseHost);
01405     return E_SUCCESS;
01406 }
01407 
01408 UINT16 CACmdLnOptions::getDatabasePort()
01409   {
01410     return m_iDatabasePort;
01411   }
01412 
01413 SINT32 CACmdLnOptions::getDatabaseName(UINT8 * name, UINT32 len)
01414   {
01415     if(m_strDatabaseName==NULL)
01416       return E_UNKNOWN;
01417     if(len<=(UINT32)strlen((char *)m_strDatabaseName))
01418       {
01419         return E_UNKNOWN;
01420       }
01421     strcpy((char*)name,(char *)m_strDatabaseName);
01422     return E_SUCCESS;
01423   }
01424 
01425 SINT32 CACmdLnOptions::getDatabaseUsername(UINT8 * user, UINT32 len)
01426   {
01427     if(m_strDatabaseUser==NULL)
01428       return E_UNKNOWN;
01429     if(len<=(UINT32)strlen((char *)m_strDatabaseUser))
01430       {
01431         return E_UNKNOWN;
01432       }
01433     strcpy((char*)user,(char *)m_strDatabaseUser);
01434     return E_SUCCESS;
01435   }
01436 
01437 SINT32 CACmdLnOptions::getDatabasePassword(UINT8 * pass, UINT32 len)
01438   {
01439     if(m_strDatabasePassword==NULL)
01440       return E_UNKNOWN;
01441     if(len<=(UINT32)strlen((char *)m_strDatabasePassword))
01442       {
01443         return E_UNKNOWN;
01444       }
01445     strcpy((char*)pass,(char *)m_strDatabasePassword);
01446     return E_SUCCESS;
01447   }
01448 
01449 SINT32 CACmdLnOptions::getAiID(UINT8 * id, UINT32 len)
01450   {
01451     if(m_strAiID==NULL)
01452       return E_UNKNOWN;
01453     if(len<=(UINT32)strlen((char *)m_strAiID))
01454       {
01455         return E_UNKNOWN;
01456       }
01457     strcpy((char*)id,(char *)m_strAiID);
01458     return E_SUCCESS;
01459   }
01460 
01461 UINT32 CACmdLnOptions::getPaymentHardLimit()
01462 {
01463   return m_iPaymentHardLimit;
01464 }
01465 
01466 UINT32 CACmdLnOptions::getPrepaidInterval()
01467 {
01468   return m_iPrepaidInterval;
01469 }
01470 
01471 UINT32 CACmdLnOptions::getPaymentSoftLimit()
01472 {
01473   return m_iPaymentSoftLimit;
01474 }
01475 
01476 UINT32 CACmdLnOptions::getPaymentSettleInterval()
01477 {
01478   return m_iPaymentSettleInterval;
01479 }
01480 
01481 #endif /* ifdef PAYMENT */
01482 
01483 SINT32 CACmdLnOptions::getOperatorSubjectKeyIdentifier(UINT8 *buffer, UINT32 *length)
01484 {
01485   if(m_OpCert == NULL)
01486   {
01487     (*length) = 0;
01488     return E_UNKNOWN;
01489   }
01490   return m_OpCert->getSubjectKeyIdentifier(buffer, length);
01491 
01492 }
01493 
01494 #ifndef ONLY_LOCAL_PROXY
01495 CAListenerInterface** CACmdLnOptions::getInfoServices(UINT32& r_size)
01496  {
01497     r_size = m_addrInfoServicesSize;
01498     return m_addrInfoServices;
01499   }
01500 
01501 SINT32 CACmdLnOptions::getCascadeName(UINT8* name,UINT32 len) const
01502   {
01503     if(m_strCascadeName==NULL)
01504         return E_UNKNOWN;
01505     if(len<=(UINT32)strlen((char*)m_strCascadeName))
01506         {
01507           return E_UNKNOWN;
01508         }
01509     strcpy((char*)name,(char*)m_strCascadeName);
01510     return E_SUCCESS;
01511   }
01512 
01513 
01514 SINT32 CACmdLnOptions::getEncryptedLogDir(UINT8* name,UINT32 len)
01515   {
01516     if(m_strEncryptedLogDir==NULL||name==NULL)
01517         return E_UNKNOWN;
01518     if(len<=(UINT32)strlen(m_strEncryptedLogDir))
01519       return E_UNKNOWN;
01520     strcpy((char*)name,m_strEncryptedLogDir);
01521     return E_SUCCESS;
01522   }
01523 #endif //ONLY_LOCAL_PROXY
01524 
01525 SINT32 CACmdLnOptions::getLogDir(UINT8* name,UINT32 len)
01526   {
01527     if(m_strLogDir==NULL||name==NULL)
01528         return E_UNKNOWN;
01529     if(len<=(UINT32)strlen(m_strLogDir))
01530         {
01531           return E_SPACE;
01532         }
01533     strcpy((char*)name,m_strLogDir);
01534     return E_SUCCESS;
01535   }
01536 
01537 SINT32 CACmdLnOptions::setLogDir(const UINT8* name,UINT32 len)
01538   {
01539     if(m_strLogDir!=NULL)
01540     {
01541       delete[] m_strLogDir;
01542       m_strLogDir = NULL;
01543     }
01544     m_strLogDir=new char[len+1];
01545     memcpy(m_strLogDir,name,len);
01546     m_strLogDir[len]=0;
01547     return E_SUCCESS;
01548   }
01549 
01550 SINT32 CACmdLnOptions::getPidFile(UINT8* pidfile,UINT32 len)
01551   {
01552     if(m_strPidFile==NULL||pidfile==NULL)
01553         return E_UNKNOWN;
01554     if(len<=(UINT32)strlen(m_strPidFile))
01555         {
01556           return E_SPACE;
01557         }
01558     strcpy((char*)pidfile,m_strPidFile);
01559     return E_SUCCESS;
01560   }
01561 
01562 
01563 SINT32 CACmdLnOptions::getUser(UINT8* user,UINT32 len)
01564 {
01565   if(m_strUser==NULL||user==NULL)
01566   {
01567     return E_UNKNOWN;
01568   }
01569   if(len<=(UINT32)strlen(m_strUser))
01570   {
01571       return E_UNKNOWN;
01572   }
01573   strcpy((char*)user,m_strUser);
01574   return E_SUCCESS;
01575 }
01576 
01577 bool CACmdLnOptions::isFirstMix()
01578 {
01579   return m_bFirstMix;
01580 }
01581 
01582 bool CACmdLnOptions::isMiddleMix()
01583 {
01584     return m_bMiddleMix;
01585 }
01586 
01587 bool CACmdLnOptions::isLastMix()
01588 {
01589     return m_bLastMix;
01590 }
01591 
01592 bool CACmdLnOptions::isLocalProxy()
01593 {
01594     return m_bLocalProxy;
01595 }
01596 
01597 
01598 #ifdef SERVER_MONITORING
01599 char *CACmdLnOptions::getMonitoringListenerHost()
01600 {
01601   return m_strMonitoringListenerHost;
01602 }
01603 
01604 UINT16 CACmdLnOptions::getMonitoringListenerPort()
01605 {
01606   return m_iMonitoringListenerPort;
01607 }
01608 #endif /* SERVER_MONITORING */
01609 
01610 #ifndef ONLY_LOCAL_PROXY
01611 
01617 SINT32 CACmdLnOptions::getMixXml(XERCES_CPP_NAMESPACE::DOMDocument* & docMixInfo)
01618 {
01619   if(m_docMixInfo == NULL)
01620   {
01621     CAMsg::printMsg(LOG_CRIT,"No mixinfo document initialized!\n");
01622     return E_UNKNOWN;
01623   }
01624   docMixInfo=m_docMixInfo;
01625   //insert (or update) the Timestamp
01626   DOMElement* elemTimeStamp=NULL;
01627   DOMElement* elemRoot=docMixInfo->getDocumentElement();
01628   if(getDOMChildByName(elemRoot, UNIVERSAL_NODE_LAST_UPDATE, elemTimeStamp, false)!=E_SUCCESS)
01629   {
01630     elemTimeStamp=createDOMElement(docMixInfo, UNIVERSAL_NODE_LAST_UPDATE);
01631     elemRoot->appendChild(elemTimeStamp);
01632   }
01633   UINT64 currentMillis;
01634   getcurrentTimeMillis(currentMillis);
01635   UINT8 tmpStrCurrentMillis[50];
01636   print64(tmpStrCurrentMillis,currentMillis);
01637   setDOMElementValue(elemTimeStamp,tmpStrCurrentMillis);
01638   return E_SUCCESS;
01639 }
01640 
01641 UINT32 CACmdLnOptions::getNumberOfTermsAndConditionsTemplates()
01642 {
01643   return m_nrOfTermsAndConditionsTemplates;
01644 }
01645 XERCES_CPP_NAMESPACE::DOMDocument **CACmdLnOptions::getAllTermsAndConditionsTemplates()
01646 {
01647   return m_termsAndConditionsTemplates;
01648 }
01649 
01650 /* a reference to the Terms and conditions document stored by this class.
01651  * this method does not return a copy of the doc so don't release it.
01652  */
01653 XERCES_CPP_NAMESPACE::DOMElement* CACmdLnOptions::getTermsAndConditions()
01654 {
01655   //DOMElement *docElement = NULL;
01656   if(m_docOpTnCs == NULL)
01657   {
01658     return NULL;
01659   }
01660   UINT8 tmpBuff[TMP_BUFF_SIZE];
01661   UINT32 tmpLen = TMP_BUFF_SIZE;
01662   memset(tmpBuff, 0, tmpLen);
01663   getOperatorSubjectKeyIdentifier(tmpBuff, &tmpLen);
01664   setDOMElementAttribute(m_docOpTnCs->getDocumentElement(), OPTIONS_ATTRIBUTE_TNC_ID, tmpBuff);
01665   return m_docOpTnCs->getDocumentElement();
01666   //docElement = m_docOpTnCs->getDocumentElement();
01667   //return (docElement == NULL) ? NULL : getElementsByTagName(docElement, OPTION_NODE_TNCS);
01668 }
01669 
01679 SINT32 CACmdLnOptions::readXmlConfiguration(XERCES_CPP_NAMESPACE::DOMDocument* & docConfig,const UINT8* const configFile)
01680   {
01681     int handle;
01682     handle=open((char*)configFile,O_BINARY|O_RDONLY);
01683     if(handle==-1)
01684       return E_FILE_OPEN;
01685     SINT32 len=filesize32(handle);
01686     UINT8* tmpChar=new UINT8[len];
01687     int ret=read(handle,tmpChar,len);
01688     close(handle);
01689     if(ret!=len)
01690       return E_FILE_READ;
01691     SINT32 retVal = readXmlConfiguration(docConfig, tmpChar, len);
01692     delete[] tmpChar;
01693     tmpChar = NULL;
01694     return retVal;
01695 }
01696 
01706 SINT32 CACmdLnOptions::readXmlConfiguration(XERCES_CPP_NAMESPACE::DOMDocument* & docConfig,const UINT8* const buf, UINT32 len)
01707 {
01708     docConfig=parseDOMDocument(buf,len);
01709     if(docConfig==NULL)
01710     {
01711       CAMsg::printMsg(LOG_CRIT, "Your configuration is not a valid XML document and therefore could not be parsed. Please repair the configuration structure or create a new configuration.\n");
01712       return E_UNKNOWN;
01713     }
01714     return E_SUCCESS;
01715 }
01716 
01717 /* this method is only for internal use in order to intialize the
01718  * mixinfo structure when the options are parsed. Don't get confused
01719  * with the method addMixInfo of class CAMix which appends an
01720  * additional timestamp.
01721  * if NULL is specified as name the name of a_node is used
01722  */
01723 SINT32 CACmdLnOptions::appendMixInfo_internal(DOMNode* a_node, bool with_subtree)
01724 {
01725   DOMNode *importedNode = NULL;
01726   DOMNode *appendedNode = NULL;
01727 
01728   if(a_node == NULL)
01729   {
01730     CAMsg::printMsg(LOG_CRIT,"No node specified!\n");
01731     return E_UNKNOWN;
01732   }
01733   if(m_docMixInfo == NULL)
01734   {
01735     CAMsg::printMsg(LOG_CRIT,"No mixinfo document initialized!\n");
01736     return E_UNKNOWN;
01737   }
01738   if(m_docMixInfo->getDocumentElement() == NULL)
01739   {
01740     CAMsg::printMsg(LOG_CRIT,"No mixinfo dom structure initialized!\n");
01741     return E_UNKNOWN;
01742   }
01743 
01744   importedNode = m_docMixInfo->importNode(a_node, with_subtree);
01745 
01746   if(importedNode != NULL)
01747   {
01749     if (importedNode->getNodeType() == DOMNode::ELEMENT_NODE)
01750     {
01751       DOMNodeList* nodesMail = getElementsByTagName((DOMElement*)importedNode, "EMail");
01752       for (UINT32 i = 0; i < nodesMail->getLength (); i++)
01753       {
01754         nodesMail->item(i)->getParentNode()->removeChild(nodesMail->item(i));
01755       }
01756     }
01757     
01758     appendedNode = m_docMixInfo->getDocumentElement()->appendChild(importedNode);
01759     if( appendedNode != NULL )
01760     {
01761       return E_SUCCESS;
01762     }
01763   }
01764   CAMsg::printMsg(LOG_CRIT,"Could not append Node \"%s\" to Mixinfo!\n", a_node->getNodeName());
01765   return E_UNKNOWN;
01766 }
01767 
01771 inline SINT32 CACmdLnOptions::addMixIdToMixInfo()
01772 {
01773   if( (m_docMixInfo != NULL) && (m_strMixID != NULL) )
01774   {
01775     return setDOMElementAttribute
01776         (m_docMixInfo->getDocumentElement(), MIXINFO_ATTRIBUTE_MIX_ID, (UINT8*) m_strMixID);
01777   }
01778   CAMsg::printMsg(LOG_CRIT,"No mixinfo document initialized!\n");
01779   return E_UNKNOWN;
01780 }
01781 
01782 
01788 SINT32 CACmdLnOptions::invokeOptionSetters (const optionSetter_pt *optionsSetters, DOMElement* optionsSource, SINT32 optionsSettersLength)
01789 {
01790   SINT32 i = 0;
01791   SINT32 ret = E_SUCCESS;
01792 
01793   if( optionsSetters == NULL )
01794   {
01795     CAMsg::printMsg(LOG_CRIT,"Error parsing config file: OptionSetters not initialized!\n");
01796     return E_UNKNOWN;
01797   }
01798 
01799   if( optionsSettersLength < 0)
01800   {
01801     CAMsg::printMsg(LOG_CRIT,"Error parsing config file: Negative number of option setters specified!\n");
01802     return E_UNKNOWN;
01803   }
01804 
01805   /* Only warn when we have a null DOM Element */
01806   if( optionsSource == NULL )
01807   {
01808     CAMsg::printMsg(LOG_INFO, "Found NULL DOM element. "
01809         "NULL element handling is delegated to the specified setter method!\n");
01810   }
01811 
01812   for(i=0; i < optionsSettersLength; i++ )
01813   {
01814     ret = (this->*(optionsSetters[i]))(optionsSource);
01815     if(ret != E_SUCCESS)
01816     {
01817       return ret;
01818     }
01819   }
01820   return E_SUCCESS;
01821 }
01822 
01823 /***********************************
01824  * general option setter functions *
01825  ***********************************/
01826 SINT32 CACmdLnOptions::setGeneralOptions(DOMElement* elemRoot)
01827 {
01828   DOMElement* elemGeneral=NULL;
01829 
01830   if (getDOMChildByName(elemRoot, OPTIONS_NODE_GENERAL,
01831               elemGeneral,false) != E_SUCCESS)
01832   {
01833     LOG_NODE_NOT_FOUND(OPTIONS_NODE_GENERAL);
01834     return E_UNKNOWN;
01835   }
01836 
01837   return invokeOptionSetters
01838     (generalOptionSetters, elemGeneral, GENERAL_OPTIONS_NR);
01839 }
01840 
01845 SINT32 CACmdLnOptions::setMixType(DOMElement* elemGeneral)
01846 {
01847   DOMElement* elemMixType=NULL;
01848   UINT8 tmpBuff[TMP_BUFF_SIZE];
01849   UINT32 tmpLen = TMP_BUFF_SIZE;
01850 
01851   if(elemGeneral == NULL) return E_UNKNOWN;
01852   ASSERT_GENERAL_OPTIONS_PARENT
01853     (elemGeneral->getNodeName(), OPTIONS_NODE_MIX_TYPE);
01854 
01855   //getMixType
01856   if (getDOMChildByName(elemGeneral, OPTIONS_NODE_MIX_TYPE,
01857               elemMixType,false) != E_SUCCESS)
01858   {
01859     LOG_NODE_NOT_FOUND(OPTIONS_NODE_MIX_TYPE);
01860     return E_UNKNOWN;
01861   }
01862 
01863   if( getDOMElementValue(elemMixType,tmpBuff,&tmpLen) == E_SUCCESS )
01864   {
01865     if(memcmp(tmpBuff,"FirstMix",8) == 0)
01866     {
01867       m_bFirstMix = true;
01868     }
01869     else if (memcmp(tmpBuff,"MiddleMix",9) == 0)
01870     {
01871       m_bMiddleMix = true;
01872     }
01873     else if (memcmp(tmpBuff,"LastMix",7) == 0)
01874     {
01875       m_bLastMix = true;
01876     }
01877     if ( appendMixInfo_internal(elemMixType, WITH_SUBTREE) != E_SUCCESS )
01878     {
01879       return E_UNKNOWN;
01880     }
01881   }
01882   else
01883   {
01884     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_MIX_TYPE);
01885     return E_UNKNOWN;
01886   }
01887   return E_SUCCESS;
01888 }
01889 
01890 SINT32 CACmdLnOptions::setMixName(DOMElement* elemGeneral)
01891 {
01892   DOMElement *elemMixName = NULL, *elemMixInfoName = NULL;
01893   UINT8 tmpBuff[TMP_BUFF_SIZE];
01894   UINT32 tmpLen = TMP_BUFF_SIZE;
01895   UINT8 *typeValue = NULL;  //(UINT8 *) OPTIONS_VALUE_NAMETYPE_DEFAULT;
01896   //uncomment the above line to enable a default name type
01897 
01898   if(elemGeneral == NULL) return E_UNKNOWN;
01899   ASSERT_GENERAL_OPTIONS_PARENT
01900     (elemGeneral->getNodeName(), OPTIONS_NODE_MIX_NAME);
01901 
01902   //Inserting the Name if given...
01903   getDOMChildByName(elemGeneral, OPTIONS_NODE_MIX_NAME, elemMixName, false);
01904   if(elemMixName != NULL)
01905   {
01906     if(getDOMElementValue(elemMixName, tmpBuff, &tmpLen) == E_SUCCESS)
01907     {
01908       m_strMixName = new char[tmpLen+1];
01909       memset(m_strMixName, 0, tmpLen+1);
01910       memcpy(m_strMixName, tmpBuff, tmpLen);
01911     }
01912     tmpLen = TMP_BUFF_SIZE;
01913     getDOMElementAttribute(elemMixName, OPTIONS_ATTRIBUTE_NAME_FOR_CASCADE, tmpBuff, &tmpLen);
01914   }
01915   else
01916   {
01917     tmpLen = 0;
01918     m_strMixName = NULL;
01919   }
01920 
01921   /* now append the values to the mix info
01922    * conditions:
01923    * - if name is set, m_strMixname points to it.
01924    * - if name type is set then it is in tmpBuff.
01925    */
01926   elemMixInfoName = createDOMElement(m_docMixInfo, MIXINFO_NODE_MIX_NAME);
01927 
01928   /* if name is set */
01929   if(m_strMixName != NULL)
01930   {
01931     setDOMElementValue(elemMixInfoName, (UINT8*) m_strMixName);
01932   }
01933 
01934   if( tmpLen != 0 ) /* if name type is set */
01935   {
01936     if( strncasecmp( ((char *)tmpBuff),
01937           OPTIONS_VALUE_OPERATOR_NAME,
01938           strlen(OPTIONS_VALUE_OPERATOR_NAME)) == 0 ) /* type is operator name*/
01939     {
01940       typeValue = (UINT8 *) OPTIONS_VALUE_OPERATOR_NAME;
01941     }
01942     else if( strncasecmp( ((char *)tmpBuff),
01943           OPTIONS_VALUE_MIX_NAME,
01944           strlen(OPTIONS_VALUE_MIX_NAME)) == 0 ) /* type is mix name*/
01945     {
01946       typeValue = (UINT8 *) OPTIONS_VALUE_MIX_NAME;
01947     }
01948   }
01949   if(typeValue != NULL)
01950   {
01951     setDOMElementAttribute(elemMixInfoName,
01952       OPTIONS_ATTRIBUTE_NAME_FOR_CASCADE, typeValue);
01953   }
01954 
01955   if(m_docMixInfo->getDocumentElement() != NULL)
01956   {
01957     m_docMixInfo->getDocumentElement()->appendChild(elemMixInfoName);
01958   }
01959   else
01960   {
01961     //Should never happen
01962     return E_UNKNOWN;
01963   }
01964   return E_SUCCESS;
01965 }
01966 
01967 SINT32 CACmdLnOptions::setMixID(DOMElement* elemGeneral)
01968 {
01969   DOMElement* elemMixID=NULL;
01970   UINT8 tmpBuff[TMP_BUFF_SIZE];
01971   UINT32 tmpLen = TMP_BUFF_SIZE;
01972   size_t mixID_strlen = 0;
01973 
01974   if(elemGeneral == NULL) return E_UNKNOWN;
01975   ASSERT_GENERAL_OPTIONS_PARENT
01976     (elemGeneral->getNodeName(), OPTIONS_NODE_MIX_NAME);
01977 
01978   getDOMChildByName(elemGeneral, OPTIONS_NODE_MIX_ID, elemMixID, false);
01979   if(elemMixID != NULL)
01980   {
01981     if(getDOMElementValue(elemMixID,tmpBuff,&tmpLen) == E_SUCCESS)
01982     {
01983       strtrim(tmpBuff);
01984       mixID_strlen = strlen((char*)tmpBuff)+1;
01985       m_strMixID = new char[strlen((char*)tmpBuff)+1];
01986       memset(m_strMixID, 0, mixID_strlen);
01987       memcpy(m_strMixID, tmpBuff, mixID_strlen);
01988 
01989       return addMixIdToMixInfo();
01990     }
01991   }
01992   return E_SUCCESS;
01993 
01994 }
01999 SINT32 CACmdLnOptions::setDynamicMix(DOMElement* elemGeneral)
02000 {
02001   // LERNGRUPPE
02002   // get Dynamic flag
02003   DOMElement* elemDynamic=NULL;
02004   UINT8 tmpBuff[TMP_BUFF_SIZE];
02005   UINT32 tmpLen = TMP_BUFF_SIZE;
02006   m_bDynamic = false;
02007 
02008   if(elemGeneral == NULL) return E_UNKNOWN;
02009   ASSERT_GENERAL_OPTIONS_PARENT
02010     (elemGeneral->getNodeName(), OPTIONS_NODE_DYNAMIC_MIX);
02011 
02012   getDOMChildByName(elemGeneral, OPTIONS_NODE_DYNAMIC_MIX, elemDynamic, false);
02013   if(elemDynamic != NULL)
02014   {
02015     if(getDOMElementValue(elemDynamic, tmpBuff, &tmpLen)==E_SUCCESS)
02016       {
02017       m_bDynamic = (strcmp("True",(char*)tmpBuff) == 0);
02018       }
02019   }
02020   if(m_bDynamic)
02021   {
02022     CAMsg::printMsg( LOG_DEBUG, "I am a dynamic mix\n");
02023   }
02024   return E_SUCCESS;
02025 }
02026 
02027 SINT32 CACmdLnOptions::setMinCascadeLength(DOMElement* elemGeneral)
02028 {
02029   DOMElement* elemMinCascadeLength = NULL;
02030   if(elemGeneral == NULL) return E_UNKNOWN;
02031   ASSERT_GENERAL_OPTIONS_PARENT
02032     (elemGeneral->getNodeName(), OPTIONS_NODE_MIN_CASCADE_LENGTH);
02033   //Inserting the min. cascade length if given...
02034   getDOMChildByName
02035     (elemGeneral, OPTIONS_NODE_MIN_CASCADE_LENGTH, elemMinCascadeLength, false);
02036   if(elemMinCascadeLength != NULL)
02037   {
02038     appendMixInfo_internal(elemMinCascadeLength, WITH_SUBTREE);
02039   }
02040   return E_SUCCESS;
02041 }
02042 
02043 SINT32 CACmdLnOptions::setCascadeNameFromOptions(DOMElement* elemGeneral)
02044 {
02045   DOMElement* elemCascadeName=NULL;
02046   UINT8 tmpBuff[TMP_BUFF_SIZE];
02047   UINT32 tmpLen = TMP_BUFF_SIZE;
02048 
02049   if(elemGeneral == NULL) return E_UNKNOWN;
02050   ASSERT_GENERAL_OPTIONS_PARENT
02051     (elemGeneral->getNodeName(), OPTIONS_NODE_CASCADE_NAME);
02052 
02053   //getCascadeName
02054   getDOMChildByName(elemGeneral, OPTIONS_NODE_CASCADE_NAME, elemCascadeName, false);
02055 
02056 #ifdef DYNAMIC_MIX
02057   bool bNeedCascadeNameFromMixID=false;
02058 #endif
02059   if(getDOMElementValue(elemCascadeName,tmpBuff,&tmpLen)==E_SUCCESS)
02060   {
02061     setCascadeName(tmpBuff);
02062   }
02063 #ifdef DYNAMIC_MIX
02064     /* LERNGRUPPE: Dynamic Mixes must have a cascade name, as MiddleMixes may be reconfigured to be FirstMixes */
02065   else
02066   {
02067     bNeedCascadeNameFromMixID=true;
02068     setCascadeName(m_strMixID);
02069   }
02070 #endif
02071   return E_SUCCESS;
02072 }
02073 
02074 SINT32 CACmdLnOptions::setUserID(DOMElement* elemGeneral)
02075 {
02076   DOMElement* elemUID=NULL;
02077   UINT8 tmpBuff[TMP_BUFF_SIZE];
02078   UINT32 tmpLen = TMP_BUFF_SIZE;
02079   UINT8 buff[255];
02080 
02081   if(elemGeneral == NULL) return E_UNKNOWN;
02082   ASSERT_GENERAL_OPTIONS_PARENT
02083     (elemGeneral->getNodeName(), OPTIONS_NODE_USER_ID);
02084 
02085   //get Username to run as...
02086   getDOMChildByName(elemGeneral, OPTIONS_NODE_USER_ID, elemUID,false);
02087 
02088   if(getDOMElementValue(elemUID,tmpBuff,&tmpLen)==E_SUCCESS)
02089   {
02090     m_strUser=new char[tmpLen+1];
02091     memcpy(m_strUser,tmpBuff,tmpLen);
02092     m_strUser[tmpLen]=0;
02093   }
02094 
02095 #ifndef WIN32
02096     if(getUser(buff,255)==E_SUCCESS) //switching user
02097       {
02098         struct passwd* pwd=getpwnam((char*)buff);
02099         if(pwd==NULL || (setegid(pwd->pw_gid)==-1) || (seteuid(pwd->pw_uid)==-1) )
02100         {
02101           if (pwd==NULL)
02102           {
02103             CAMsg::printMsg(LOG_ERR,
02104                 "Could not switch to effective user '%s'! Reason: User '%s' does not exist on this system. Create this user first.\n",
02105                             buff, buff);
02106           }
02107           else
02108           {
02109             CAMsg::printMsg(LOG_ERR,"Could not switch to effective user '%s'! Reason: %s (%i)\n",
02110                 buff, GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
02111           }
02112         }
02113         else
02114           CAMsg::printMsg(LOG_INFO,"Switched to effective user '%s'!\n",buff);
02115       }
02116 
02117     if(geteuid()==0)
02118       CAMsg::printMsg(LOG_WARNING,"Mix is running as root/superuser!\n");
02119 #endif
02120   
02121   
02122 
02123   return E_SUCCESS;
02124 }
02125 
02126 SINT32 CACmdLnOptions::setNrOfFileDescriptors(DOMElement* elemGeneral)
02127 {
02128   DOMElement* elemNrFd=NULL;
02129   UINT32 tmp = 0;
02130 
02131   if(elemGeneral == NULL) return E_UNKNOWN;
02132   ASSERT_GENERAL_OPTIONS_PARENT
02133     (elemGeneral->getNodeName(), OPTIONS_NODE_FD_NR);
02134 
02135   //get Number of File Descriptors to use
02136   getDOMChildByName(elemGeneral, OPTIONS_NODE_FD_NR, elemNrFd, false);
02137 
02138   if(getDOMElementValue(elemNrFd,&tmp) == E_SUCCESS)
02139   {
02140     m_nrOfOpenFiles=tmp;
02141   }
02142   
02143 #ifndef WIN32
02144 
02145     struct rlimit coreLimit;
02146     coreLimit.rlim_cur = coreLimit.rlim_max = RLIM_INFINITY;
02147     if (setrlimit(RLIMIT_CORE, &coreLimit) != 0)
02148     {
02149       CAMsg::printMsg(LOG_CRIT,"Could not set RLIMIT_CORE (max core file size) to unlimited size. -- Core dumps might not be generated!\n",m_nrOfOpenFiles);
02150     }
02151     
02152     if(m_nrOfOpenFiles>0)
02153       {
02154         struct rlimit lim;
02155         // Set the new MAX open files limit
02156         lim.rlim_cur = lim.rlim_max = m_nrOfOpenFiles;
02157         if (setrlimit(RLIMIT_NOFILE, &lim) != 0)
02158         {
02159           CAMsg::printMsg(LOG_CRIT,"Could not set MAX open files to: %u Reason: %s (%i) \nYou might have insufficient user rights. If so, switch to a privileged user or do not set the number of file descriptors. -- Exiting!\n",
02160               m_nrOfOpenFiles, GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
02161           exit(EXIT_FAILURE);
02162         }
02163       }
02164 #endif  
02165   
02166   return E_SUCCESS;
02167 }
02168 
02169 SINT32 CACmdLnOptions::setDaemonMode(DOMElement* elemGeneral)
02170 {
02171   DOMElement* elemDaemonMode = NULL;
02172   UINT8 tmpBuff[TMP_BUFF_SIZE];
02173   UINT32 tmpLen = TMP_BUFF_SIZE;
02174 
02175   if(elemGeneral == NULL) return E_UNKNOWN;
02176   ASSERT_GENERAL_OPTIONS_PARENT
02177     (elemGeneral->getNodeName(), OPTIONS_NODE_DAEMON);
02178 
02179   //get Run as Daemon
02180   getDOMChildByName(elemGeneral, OPTIONS_NODE_DAEMON, elemDaemonMode,false);
02181 
02182   if(getDOMElementValue(elemDaemonMode, tmpBuff, &tmpLen) == E_SUCCESS &&
02183     memcmp(tmpBuff,"True",4)==0)
02184   {
02185     m_bDaemon=true;
02186   }
02187   return E_SUCCESS;
02188 }
02189 
02190 SINT32 CACmdLnOptions::setMaxUsers(DOMElement* elemGeneral)
02191 {
02192   DOMElement* elemMaxUsers=NULL;
02193   UINT32 tmp = 0;
02194 
02195   if(elemGeneral == NULL) return E_UNKNOWN;
02196   ASSERT_GENERAL_OPTIONS_PARENT
02197     (elemGeneral->getNodeName(), OPTIONS_NODE_MAX_USERS);
02198 
02199   // get max users
02200   getDOMChildByName(elemGeneral, OPTIONS_NODE_MAX_USERS, elemMaxUsers, false);
02201   if(elemMaxUsers!=NULL)
02202   {
02203     if(getDOMElementValue(elemMaxUsers, &tmp)==E_SUCCESS)
02204     {
02205       m_maxNrOfUsers = tmp;
02206     }
02207   }
02208   return E_SUCCESS;
02209 }
02210 
02211 
02212 SINT32 CACmdLnOptions::initLogging()
02213 {
02214   SINT32 ret = E_SUCCESS;
02215   UINT8 buff[2000];
02216   UINT32 iLogOptions = 0;
02217   
02218   CAMsg::init();
02219       
02220 
02221 #ifndef ONLY_LOCAL_PROXY
02222   if(isSyslogEnabled())
02223   {
02224     iLogOptions |= MSG_LOG; 
02225   }
02226 #endif
02227   if(getLogDir((UINT8*)buff,2000)==E_SUCCESS)
02228   {
02229     if(getCompressLogs())
02230       iLogOptions |= MSG_COMPRESSED_FILE;
02231     else
02232       iLogOptions |= MSG_FILE;
02233   }
02234 #ifndef ONLY_LOCAL_PROXY
02235 
02236   if (m_bLogConsole || iLogOptions == 0)
02237   {
02238     iLogOptions |= MSG_STDOUT;
02239   }
02240   ret = CAMsg::setLogOptions(iLogOptions);
02241   
02242   if (strcmp(m_strLogLevel,"info") == 0)
02243   {
02244     CAMsg::setLogLevel(LOG_INFO);
02245   }
02246   else if (strcmp(m_strLogLevel,"warning") == 0)
02247   {
02248     CAMsg::setLogLevel(LOG_WARNING);
02249   }
02250   else if (strcmp(m_strLogLevel,"error") == 0)
02251   {
02252     CAMsg::setLogLevel(LOG_ERR);
02253   }
02254   else if (strcmp(m_strLogLevel,"critical") == 0)
02255   {
02256     CAMsg::setLogLevel(LOG_CRIT);
02257   }
02258   
02259   if(isEncryptedLogEnabled())
02260   {
02261     SINT32 retEncr;
02262     if ((retEncr = CAMsg::openEncryptedLog()) != E_SUCCESS)
02263     {
02264       CAMsg::printMsg(LOG_ERR,"Could not open encrypted log - exiting!\n");
02265       return retEncr;
02266     }
02267   }
02268 #endif
02269 
02270   if(getDaemon() && ret != E_SUCCESS) 
02271   {
02272     CAMsg::printMsg(LOG_CRIT, "We need a log file in daemon mode in order to get any messages! Exiting...\n");
02273     return ret;
02274   }
02275   
02276   return E_SUCCESS;
02277 }
02278 
02279 SINT32 CACmdLnOptions::setLoggingOptions(DOMElement* elemGeneral)
02280 {
02281   //get Logging
02282   DOMElement* elemLogging=NULL;
02283   DOMElement* elemEncLog=NULL;
02284   DOMElement* elem=NULL;
02285 
02286   UINT8 tmpBuff[TMP_BUFF_SIZE];
02287   UINT32 tmpLen = TMP_BUFF_SIZE;
02288 
02289   SINT32 maxLogFilesTemp = 0;
02290   if(elemGeneral == NULL) return E_UNKNOWN;
02291   ASSERT_GENERAL_OPTIONS_PARENT
02292     (elemGeneral->getNodeName(), OPTIONS_NODE_LOGGING);
02293 
02294   getDOMChildByName(elemGeneral, OPTIONS_NODE_LOGGING, elemLogging, false);
02295   if(elemLogging != NULL)
02296   {
02297     if (getDOMElementAttribute(elemLogging, "level", tmpBuff, &tmpLen) == E_SUCCESS)
02298     {
02299       strtrim(tmpBuff);
02300       toLower(tmpBuff);
02301       m_strLogLevel = new char[strlen((char*)tmpBuff)+1];
02302       strcpy(m_strLogLevel, (char*)tmpBuff);
02303     }
02304     else
02305     {
02306       m_strLogLevel = new char[strlen("debug")+1];
02307       strcpy(m_strLogLevel, "debug");
02308     }
02309     
02310     
02311     
02312     getDOMChildByName(elemLogging, OPTIONS_NODE_LOGGING_FILE, elem, false);
02313     tmpLen = TMP_BUFF_SIZE;
02314     if(getDOMElementValue(elem, tmpBuff, &tmpLen) == E_SUCCESS)
02315     {
02316       strtrim(tmpBuff);
02317       m_strLogDir = new char[strlen((char*)tmpBuff)+1];
02318       strcpy(m_strLogDir, (char*)tmpBuff);
02319       getDOMElementAttribute
02320         (elem, OPTIONS_ATTRIBUTE_LOGGING_MAXFILESIZE, m_maxLogFileSize);
02321       //Set maximum number of logging files
02322       //CAMsg::printMsg(LOG_ERR,"!!!!!!!!\n");
02323       if((getDOMElementAttribute
02324           (elem, OPTIONS_ATTRIBUTE_LOGGING_MAXFILES, &maxLogFilesTemp) != E_SUCCESS) ||
02325         (maxLogFilesTemp == 0) )
02326       {
02327         m_maxLogFiles = LOGGING_MAXFILES_DEFAULT;
02328       }
02329       else
02330       {
02331         if(maxLogFilesTemp < 0)
02332         {
02333           //CAMsg::printMsg(LOG_ERR,"Negative number of log files specified.\n");
02334           return E_UNKNOWN;
02335         }
02336         m_maxLogFiles = (UINT32) maxLogFilesTemp;
02337         //CAMsg::printMsg(LOG_ERR,"Max log files are %u\n", m_maxLogFiles);
02338       }
02339     }
02340     getDOMChildByName(elemLogging, OPTIONS_NODE_SYSLOG, elem, false);
02341     tmpLen = TMP_BUFF_SIZE;
02342     memset(tmpBuff, 0, tmpLen);
02343     if( (getDOMElementValue(elem, tmpBuff, &tmpLen) == E_SUCCESS) &&
02344       (memcmp(tmpBuff,"True",4) == 0) )
02345     {
02346       m_bSyslog = true;
02347     }
02348 
02349     getDOMChildByName(elemLogging, OPTIONS_NODE_LOGGING_CONSOLE, elem, false);
02350     tmpLen = TMP_BUFF_SIZE;
02351     memset(tmpBuff, 0, tmpLen);
02352     if( (getDOMElementValue(elem, tmpBuff, &tmpLen) == E_SUCCESS) &&
02353       (memcmp(tmpBuff,"True",4) == 0) )
02354     {
02355       m_bLogConsole = true;
02356     }
02357 
02358     //get Encrypted Log Info
02359     if( getDOMChildByName
02360         (elemLogging, OPTIONS_NODE_ENCRYPTED_LOG, elemEncLog,false) == E_SUCCESS )
02361     {
02362       m_bIsEncryptedLogEnabled = true;
02363       getDOMChildByName(elemEncLog, OPTIONS_NODE_LOGGING_FILE, elem, false);
02364 
02365       tmpLen = TMP_BUFF_SIZE;
02366       memset(tmpBuff, 0, tmpLen);
02367       if( getDOMElementValue(elem, tmpBuff, &tmpLen) == E_SUCCESS )
02368         {
02369           strtrim(tmpBuff);
02370           m_strEncryptedLogDir = new char[strlen((char*)tmpBuff)+1];
02371           strcpy(m_strEncryptedLogDir, (char*)tmpBuff);
02372         }
02373       DOMElement* elemKeyInfo;
02374       DOMElement* elemX509Data;
02375       if(getDOMChildByName
02376           (elemEncLog, OPTIONS_NODE_LOGGING_KEYINFO, elemKeyInfo, false) == E_SUCCESS &&
02377          getDOMChildByName
02378           (elemKeyInfo, OPTIONS_NODE_X509DATA, elemX509Data, false) == E_SUCCESS )
02379       {
02380         m_pLogEncryptionCertificate =
02381           CACertificate::decode(elemX509Data->getFirstChild(), CERT_X509CERTIFICATE);
02382       }
02383     }
02384     else
02385     {
02386       m_bIsEncryptedLogEnabled=false;
02387     }
02388     
02389   }
02390   
02391   SINT32 ret = initLogging();
02392   if (ret == E_SUCCESS)
02393   {
02394     CAMsg::printMsg(LOG_INFO,MIX_VERSION_INFO);
02395     if (MIX_VERSION_TESTING)
02396     {
02397       CAMsg::printMsg(LOG_WARNING, MIX_VERSION_TESTING_TEXT);
02398     }
02399   }
02400 
02401   return ret;
02402 }
02403 
02404 /* append the mix description to the mix info DOM structure
02405  * this is a main option (child of <MixConfiguration>)
02406  */
02407 SINT32  CACmdLnOptions::setMixDescription(DOMElement* elemRoot)
02408 {
02409   SINT32 ret = E_SUCCESS;
02410   DOMElement* elemMixDescription = NULL;
02411   if(elemRoot == NULL)
02412   {
02413     return E_UNKNOWN;
02414   }
02415   ret = getDOMChildByName
02416       (elemRoot, OPTIONS_NODE_DESCRIPTION, elemMixDescription, false);
02417 
02418   if(elemMixDescription != NULL )
02419   {
02420     DOMNode* tmpChild = elemMixDescription->getFirstChild();
02421     while( (tmpChild != NULL) && (ret == E_SUCCESS) )
02422     {
02423       ret = appendMixInfo_internal(tmpChild, WITH_SUBTREE);
02424       tmpChild=tmpChild->getNextSibling();
02425     }
02426   }
02427   return ret;
02428 }
02429 
02430 /***************************************
02431  * certificate option setter functions *
02432  ***************************************/
02433 SINT32 CACmdLnOptions::setCertificateOptions(DOMElement* elemRoot)
02434 {
02435 
02436   DOMElement* elemCertificates;
02437 
02438   if (getDOMChildByName
02439       (elemRoot, OPTIONS_NODE_CERTIFICATE_LIST, elemCertificates, false) != E_SUCCESS)
02440   {
02441     LOG_NODE_NOT_FOUND(OPTIONS_NODE_CERTIFICATE_LIST);
02442     return E_UNKNOWN;
02443   }
02444 
02445   return invokeOptionSetters(certificateOptionSetters, elemCertificates, m_nCertificateOptionsSetters);
02446 }
02447 
02448 SINT32 CACmdLnOptions::setOwnCertificate(DOMElement *elemCertificates)
02449 {
02450   DOMElement* elemOwnCert=NULL;
02451   UINT8 tmpBuff[TMP_BUFF_SIZE];
02452   UINT32 tmpLen = TMP_BUFF_SIZE;
02453 
02454   UINT8 passwd[500];
02455   passwd[0] = 0;
02456 
02457   if(elemCertificates == NULL) return E_UNKNOWN;
02458   ASSERT_CERTIFICATES_OPTIONS_PARENT
02459     (elemCertificates->getNodeName(), OPTIONS_NODE_OWN_CERTIFICATE);
02460 
02461   //Own Certiticate first
02462   getDOMChildByName(elemCertificates, OPTIONS_NODE_OWN_CERTIFICATE, elemOwnCert, false);
02463   if (elemOwnCert == NULL)
02464   {
02465     LOG_NODE_NOT_FOUND(OPTIONS_NODE_OWN_CERTIFICATE);
02466     return E_UNKNOWN;
02467   }
02468 
02469   /*m_pSignKey = new CASignature();
02470 
02471   if(m_pSignKey->setSignKey
02472       (elemOwnCert->getFirstChild(), SIGKEY_PKCS12) != E_SUCCESS)
02473   {
02474     //Maybe not an empty passwd
02475     printf("I need a passwd for the SignKey: ");
02476     fflush(stdout);
02477     readPasswd(passwd, 500);
02478     if(m_pSignKey->setSignKey
02479         (elemOwnCert->getFirstChild(),
02480          SIGKEY_PKCS12,(char*)passwd) != E_SUCCESS)
02481     {
02482       CAMsg::printMsg(LOG_CRIT,"Could not read own signature key!\n");
02483       delete m_pSignKey;
02484       m_pSignKey=NULL;
02485     }
02486   }*/
02487 
02488   /*m_pOwnCertificate =
02489     CACertificate::decode(elemOwnCert->getFirstChild(), CERT_PKCS12, (char*)passwd);
02490   if (m_pOwnCertificate == NULL)
02491   {
02492     CAMsg::printMsg(LOG_CRIT, "Could not decode mix certificate!\n");
02493     return E_UNKNOWN;
02494   }*/
02495 
02496   // new
02497   //m_ownCertsLength = 0;
02498   //m_opCertsLength = 0;
02499 
02500   //decode OpCerts
02501   UINT32 opCertsLen = m_opCertList->getLength();
02502   CACertificate** opCerts=new CACertificate*[opCertsLen];
02503   for(UINT32 j=0; j<opCertsLen; j++)
02504   {
02505     DOMNode* a_opCert = m_opCertList->item(j);
02506     opCerts[j] = CACertificate::decode(a_opCert,CERT_X509CERTIFICATE);
02507     if(opCerts[j] == NULL)
02508     {
02509       CAMsg::printMsg(LOG_CRIT, "Error while decoding operator certificates!");
02510       delete[] opCerts; 
02511       return E_UNKNOWN;
02512     }
02513   }
02514 
02515   DOMNodeList* ownCertList = getElementsByTagName(elemOwnCert, OPTIONS_NODE_X509_PKCS12);
02516 
02517   m_pMultiSignature = new CAMultiSignature();
02518   for (UINT32 i=0; i<ownCertList->getLength(); i++)
02519   {
02520     DOMNode* a_cert = ownCertList->item(i);
02521     CASignature* signature = new CASignature();
02522     CACertStore* certs = new CACertStore();
02523 
02524     //try to get signature key from ownCert
02525     if(signature->setSignKey(a_cert, SIGKEY_PKCS12, (char*)passwd) != E_SUCCESS)
02526     {
02527       //Read password if necessary
02528       printf("I need a password for the private Mix certificate nr. %d: ", i+1);
02529       fflush(stdout);
02530       readPasswd(passwd,500);
02531       printf("\n");
02532       if(signature->setSignKey(a_cert, SIGKEY_PKCS12, (char*)passwd) != E_SUCCESS)
02533       {
02534         CAMsg::printMsg(LOG_CRIT,"Unable to load private Mix certificate nr. %d! Please check your password.\n", i+1);
02535         delete signature;
02536         delete[] opCerts; 
02537         signature = NULL;
02538         return E_UNKNOWN;
02539       }
02540     }
02541     //decode own certifciate
02542     CACertificate* tmpCert = CACertificate::decode(a_cert, CERT_PKCS12, (char*)passwd);
02543     if(tmpCert== NULL)
02544     {
02545       CAMsg::printMsg(LOG_CRIT, "Error while getting own certificate %d!\n", i+1);
02546       delete[] opCerts; 
02547       return E_UNKNOWN;
02548     }
02549 
02550     //get SKI
02551     UINT32 tmpSKIlen = 255;
02552     UINT8 tmpSKI[255];
02553     if(tmpCert->getSubjectKeyIdentifier(tmpSKI, &tmpSKIlen) != E_SUCCESS)
02554     {
02555       CAMsg::printMsg(LOG_CRIT, "Error while getting SKI of own certificate %d!\n", i+1);
02556       delete[] opCerts; 
02557       return E_UNKNOWN;
02558     }
02559     //CAMsg::printMsg(LOG_DEBUG, "SKI of own cert %d is: %s\n", i+1, tmpSKI);
02560     //get AKI
02561     UINT32 tmpAKIlen = 255;
02562     UINT8 tmpAKI[255];
02563     if(tmpCert->getAuthorityKeyIdentifier(tmpAKI, &tmpAKIlen) != E_SUCCESS)
02564     {
02565       CAMsg::printMsg(LOG_WARNING, "Could not get AKI of own certificate. This is not a critical problem, but you have a very old mix certificate. Create a new one as soon as possible.\n");
02566     }
02567     else
02568     {
02569       //CAMsg::printMsg(LOG_DEBUG, "AKI of own cert %d is: %s\n", i+1, tmpAKI);
02570     }
02571     //try to find right opCert
02572     for(UINT32 j=0; j<opCertsLen; j++)
02573     {
02574       if(tmpCert->verify(opCerts[j]) == E_SUCCESS)
02575       {
02576         //found right operator cert -> add it to store
02577         // CAMsg::printMsg(LOG_DEBUG, "Found operator cert for sign key %d!\n", i+1);
02578         certs->add(opCerts[j]);
02579         break;
02580       }
02581     }
02582     if(certs->getNumber() == 0)
02583     {
02584       CAMsg::printMsg(LOG_CRIT, "Could not find operator cert for sign key %d! Please check your configuration. Exiting...\n", i+1);
02585       exit(EXIT_FAILURE);
02586     }
02587     //add own cert to store
02588     certs->add(tmpCert);
02589     //get Raw SKI
02590     UINT32 tmpRawSKIlen = 255;
02591     UINT8 tmpRawSKI[255];
02592     if(tmpCert->getRawSubjectKeyIdentifier(tmpRawSKI, &tmpRawSKIlen) != E_SUCCESS)
02593     {
02594       delete[] opCerts; 
02595       return E_UNKNOWN;
02596     }
02597     if (certs->getNumber() < 2)
02598     {
02599       CAMsg::printMsg(LOG_CRIT, "We have less than two certificates (only %d), but we need at least one mix and one operator certificate. There must be something wrong with the cert store. Exiting...\n", certs->getNumber());
02600       exit(EXIT_FAILURE);
02601     }
02602     CAMsg::printMsg(LOG_DEBUG, "Adding Sign-Key %d with %d certificate(s).\n", i+1, certs->getNumber());
02603     m_pMultiSignature->addSignature(signature, certs, tmpRawSKI, tmpRawSKIlen);
02604   }
02605   if (m_pMultiSignature->getSignatureCount() == 0)
02606   {
02607     CAMsg::printMsg(LOG_CRIT, "Could not set a signature key for MultiCert!\n");
02608     delete m_pMultiSignature;
02609     m_pMultiSignature = NULL;
02610     delete[] opCerts; 
02611     return E_UNKNOWN;
02612   }
02613   //end new
02614   /*if ( (m_pOwnCertificate->getSubjectKeyIdentifier(tmpBuff, &tmpLen) != E_SUCCESS) &&
02615         (m_strMixID == NULL))
02616   {
02617     LOG_NODE_NOT_FOUND(OPTIONS_NODE_MIX_ID);
02618     return E_UNKNOWN;
02619   }*/
02620   //check Mix-ID
02621   if(m_pMultiSignature->getXORofSKIs(tmpBuff, tmpLen) != E_SUCCESS)
02622   {
02623     delete[] opCerts; 
02624     return E_UNKNOWN;
02625   }
02626 
02627   if(m_strMixID != NULL )
02628   {
02629     if(strncmp(m_strMixID, (char*)tmpBuff, strlen((char*)tmpBuff) ) != 0)
02630     {
02631       CAMsg::printMsg(LOG_CRIT,"The configuration file seems inconsistent: it contains another Mix ID (%s) than calculated from the Mix certificate(s), which is %s. Please re-import you mix certificate in the configuration tool, or set the correct mix ID manually by editing the configuration file.\n", m_strMixID, tmpBuff);
02632       delete[] opCerts; 
02633       return E_UNKNOWN;
02634     }
02635   }
02636   else
02637   {
02638     m_strMixID=new char[strlen((char*)tmpBuff)+1];
02639     m_strMixID[strlen((char*)tmpBuff)]= (char) 0;
02640     strcpy(m_strMixID,(char*) tmpBuff);
02641     delete[] opCerts; 
02642     return addMixIdToMixInfo();
02643   }
02644   
02645 #ifdef PAYMENT
02646   if (m_strAiID != NULL && m_pMultiSignature->findSKI(m_strAiID) != E_SUCCESS)
02647   {
02648     CAMsg::printMsg(LOG_CRIT, "Your price certificate does not fit to your mix certificate(s). Please import the proper price certificate or mix certificate.\n");
02649   }
02650 #endif
02651   
02652 #ifdef DYNAMIC_MIX
02653     /* LERNGRUPPE: Dynamic Mixes must have a cascade name, as MiddleMixes may be reconfigured to be FirstMixes */
02654   if(bNeedCascadeNameFromMixID)
02655   {
02656     m_strCascadeName = new char[strlen(m_strMixID) + 1];
02657     memset(m_strCascadeName, 0, strlen(m_strMixID) + 1);
02658     strncpy(m_strCascadeName, m_strMixID, strlen(m_strMixID)+1);
02659   }
02660 #endif
02661   delete[] opCerts; 
02662   return E_SUCCESS;
02663 }
02664 
02665 SINT32 CACmdLnOptions::setOwnOperatorCertificate(DOMElement *elemCertificates)
02666 {
02667   DOMElement* elemOpCert = NULL;
02668   DOMElement *opCertX509 = NULL;
02669 
02670   if(elemCertificates == NULL) return E_UNKNOWN;
02671   ASSERT_CERTIFICATES_OPTIONS_PARENT
02672     (elemCertificates->getNodeName(), OPTIONS_NODE_OWN_OPERATOR_CERTIFICATE);
02673 
02674   //then Operator Certificate
02675   if (getDOMChildByName
02676      (elemCertificates, OPTIONS_NODE_OWN_OPERATOR_CERTIFICATE,
02677       elemOpCert, false) != E_SUCCESS)
02678   {
02679     LOG_NODE_NOT_FOUND(OPTIONS_NODE_OWN_OPERATOR_CERTIFICATE);
02680     return E_UNKNOWN;
02681   }
02682 
02683   if (elemOpCert != NULL)
02684   {
02685     m_opCertList = getElementsByTagName(elemOpCert, "X509Certificate");
02686 
02687     getDOMChildByName(elemOpCert, OPTIONS_NODE_X509_CERTIFICATE, opCertX509, true);
02688     if( opCertX509 != NULL)
02689     {
02690       m_OpCert = CACertificate::decode(opCertX509, CERT_X509CERTIFICATE);
02691     }
02692     else
02693     {
02694       LOG_NODE_NOT_FOUND(OPTIONS_NODE_X509_CERTIFICATE);
02695       return E_UNKNOWN;
02696     }
02697   }
02698   return E_SUCCESS;
02699 }
02700 
02701 SINT32 CACmdLnOptions::setMixCertificateVerification(DOMElement *elemCertificates)
02702 {
02703   DOMElement *elemMixVerify;
02704   UINT8 tmpBuff[TMP_BUFF_SIZE];
02705   UINT32 tmpLen = TMP_BUFF_SIZE;
02706 
02707   if(elemCertificates == NULL) return E_UNKNOWN;
02708     ASSERT_CERTIFICATES_OPTIONS_PARENT
02709       (elemCertificates->getNodeName(), OPTIONS_NODE_MIX_CERTIFICATE_VERIFICATION);
02710 
02711   getDOMChildByName(elemCertificates, OPTIONS_NODE_MIX_CERTIFICATE_VERIFICATION, elemMixVerify, false);
02712   if(elemMixVerify != NULL)
02713   {
02714     if(getDOMElementValue(elemMixVerify, tmpBuff, &tmpLen) == E_SUCCESS &&
02715         memcmp(tmpBuff,"True",4)==0)
02716     {
02717       m_bVerifyMixCerts = true;
02718       m_pTrustedRootCertificates = new CACertStore();
02719       CAMsg::printMsg(LOG_INFO, "Mix certificate verification is enabled.\n");
02720     }
02721   }
02722   return E_SUCCESS;
02723 }
02724 
02725 SINT32 CACmdLnOptions::setNextMixCertificate(DOMElement *elemCertificates)
02726 {
02727   DOMElement* elemNextCert = NULL;
02728 
02729   if(!m_bVerifyMixCerts)
02730   {
02731     if(elemCertificates == NULL) return E_UNKNOWN;
02732     ASSERT_CERTIFICATES_OPTIONS_PARENT
02733       (elemCertificates->getNodeName(), OPTIONS_NODE_NEXT_MIX_CERTIFICATE);
02734 
02735     //nextMixCertificate if given
02736     getDOMChildByName(elemCertificates, OPTIONS_NODE_NEXT_MIX_CERTIFICATE, elemNextCert,false);
02737     if(elemNextCert!=NULL)
02738     {
02739       m_pNextMixCertificate=
02740         CACertificate::decode(elemNextCert->getFirstChild(),CERT_X509CERTIFICATE);
02741       if(m_pNextMixCertificate == NULL)
02742       {
02743         CAMsg::printMsg(LOG_CRIT,"Could not decode the certificate of the next mix!\n");
02744         return E_UNKNOWN;
02745       }
02746     }
02747   }
02748   return E_SUCCESS;
02749 
02750 }
02751 
02752 SINT32 CACmdLnOptions::setPrevMixCertificate(DOMElement *elemCertificates)
02753 {
02754   //prevMixCertificate if given
02755   DOMElement* elemPrevCert=NULL;
02756 
02757   if(!m_bVerifyMixCerts)
02758   {
02759     if(elemCertificates == NULL) return E_UNKNOWN;
02760     ASSERT_CERTIFICATES_OPTIONS_PARENT
02761       (elemCertificates->getNodeName(), OPTIONS_NODE_PREV_MIX_CERTIFICATE);
02762 
02763     getDOMChildByName(elemCertificates, OPTIONS_NODE_PREV_MIX_CERTIFICATE, elemPrevCert, false);
02764     if(elemPrevCert!=NULL)
02765     {
02766       m_pPrevMixCertificate=
02767         CACertificate::decode(elemPrevCert->getFirstChild(),CERT_X509CERTIFICATE);
02768     }
02769   }
02770   return E_SUCCESS;
02771 
02772 }
02773 
02774 SINT32 CACmdLnOptions::setTrustedRootCertificates(DOMElement *elemCertificates)
02775 {
02776   DOMElement* elemTrustedCerts=NULL;
02777   DOMNodeList* trustedCerts=NULL;
02778   CACertificate* cert;
02779 
02780   if(m_bVerifyMixCerts)
02781   {
02782     if(elemCertificates == NULL) return E_UNKNOWN;
02783       ASSERT_CERTIFICATES_OPTIONS_PARENT
02784         (elemCertificates->getNodeName(), OPTIONS_NODE_TRUSTED_ROOT_CERTIFICATES);
02785 
02786     getDOMChildByName(elemCertificates, OPTIONS_NODE_TRUSTED_ROOT_CERTIFICATES, elemTrustedCerts, false);
02787     if(elemTrustedCerts!=NULL)
02788     {
02789       trustedCerts = getElementsByTagName(elemTrustedCerts, OPTIONS_NODE_X509_CERTIFICATE);
02790 
02791       for(UINT32 i=0; i<trustedCerts->getLength(); i++)
02792       {
02793         cert = CACertificate::decode(trustedCerts->item(i), CERT_X509CERTIFICATE);
02794         if(cert != NULL)
02795         {
02796           m_pTrustedRootCertificates->add(cert);
02797         }
02798         else
02799         {
02800           CAMsg::printMsg(LOG_WARNING, "Root certificate could not be decoded\n");
02801         }
02802       }
02803     }
02804     else
02805     {
02806       LOG_NODE_NOT_FOUND(OPTIONS_NODE_TRUSTED_ROOT_CERTIFICATES);
02807       return E_UNKNOWN;
02808     }
02809     if(m_pTrustedRootCertificates->getNumber() == 0)
02810     {
02811       CAMsg::printMsg(LOG_CRIT, "No trusted root certificates found.\n");
02812       return E_UNKNOWN;
02813     }
02814     CAMsg::printMsg(LOG_INFO, "Loaded %d trusted root certificates.\n", m_pTrustedRootCertificates->getNumber());
02815   }
02816   return E_SUCCESS;
02817 }
02818 
02819 /**************************************
02820  * accounting option setter functions *
02821  **************************************/
02822 SINT32 CACmdLnOptions::setAccountingOptions(DOMElement *elemRoot)
02823 {
02824   // the accoutning options are added by Bastian Voigt
02825 #ifdef PAYMENT
02826   DOMElement* elemAccounting=NULL;
02827   if (getDOMChildByName
02828       (elemRoot, OPTIONS_NODE_ACCOUNTING, elemAccounting, false) != E_SUCCESS)
02829   {
02830     LOG_NODE_NOT_FOUND(OPTIONS_NODE_ACCOUNTING);
02831     return E_UNKNOWN;
02832   }
02833 
02834   return invokeOptionSetters
02835     (accountingOptionSetters, elemAccounting, ACCOUNTING_OPTIONS_NR);
02836 #endif
02837 
02838   return E_SUCCESS;
02839 }
02840 
02841 SINT32 CACmdLnOptions::setPriceCertificate(DOMElement *elemAccounting)
02842 {
02843 
02844 #ifdef PAYMENT
02845   DOMElement* elemPriceCert = NULL;
02846 
02847   if(elemAccounting == NULL) return E_UNKNOWN;
02848    ASSERT_ACCOUNTING_OPTIONS_PARENT
02849     (elemAccounting->getNodeName(), OPTIONS_NODE_PRICE_CERTIFICATE);
02850 
02851   //function in CAUtil, last param is "deep", needs to be set to include child elems
02852   getDOMChildByName
02853     (elemAccounting, OPTIONS_NODE_PRICE_CERTIFICATE, elemPriceCert, false);
02854   if (elemPriceCert == NULL)
02855   {
02856     CAMsg::printMsg(LOG_CRIT, "Did you really want to compile the mix with payment support?\n");
02857     LOG_NODE_NOT_FOUND(OPTIONS_NODE_PRICE_CERTIFICATE);
02858     return E_UNKNOWN;
02859   }
02860   else
02861   {
02862     /*UINT8 digest[SHA_DIGEST_LENGTH];
02863     UINT8* out=new UINT8[5000];
02864     UINT32 outlen=5000;
02865 
02866     DOM_Output::makeCanonical(elemPriceCert,out,&outlen);
02867     out[outlen] = 0;
02868 //#ifdef DEBUG
02869     CAMsg::printMsg(LOG_DEBUG, "price cert (%u bytes) to be hashed: %s\n",outlen, out);
02870 //#endif
02871     SHA1(out,outlen,digest);
02872     delete[] out;
02873     out = NULL;
02874 
02875     UINT32 len2 = 1024;
02876     UINT8* tmpBuff2 = new UINT8[len2+1];
02877     memset(tmpBuff2, 0, len2+1);
02878     CABase64::encode(digest,SHA_DIGEST_LENGTH, tmpBuff2, &len2);
02879     CAMsg::printMsg(LOG_CRIT,"hash: %s\n", tmpBuff2);
02880     exit(0);*/
02881     m_pPriceCertificate = CAXMLPriceCert::getInstance(elemPriceCert);
02882     if (m_pPriceCertificate == NULL) 
02883     {
02884       CAMsg::printMsg(LOG_CRIT, "Could not parse price certificate!");
02885       return E_UNKNOWN;
02886     }
02887     m_strAiID = m_pPriceCertificate->getSubjectKeyIdentifier();
02888     
02889     if (m_pMultiSignature != NULL && m_pMultiSignature->findSKI(m_strAiID) != E_SUCCESS)
02890     {
02891         CAMsg::printMsg(LOG_CRIT,"Your price certificate does not fit to your mix certificate(s). Please import the proper price certificate or mix certificate.\n");
02892         return E_UNKNOWN;
02893     }
02894 
02895     if (m_pBI == NULL)
02896     {
02897       CAMsg::printMsg(LOG_CRIT,"Could not verify price certificate, as no payment instance was found!\n");
02898       return E_UNKNOWN;
02899     }
02900 
02901 
02902     if (CAMultiSignature::verifyXML(elemPriceCert, m_pBI->getCertificate()) != E_SUCCESS)
02903     {
02904       CAMsg::printMsg(LOG_CRIT,"Signature of price certificate is invalid! It may be damaged, or maybe you are using the wrong payment instance certificate?\n");
02905       return E_UNKNOWN;
02906     }
02907 
02908   }
02909 
02910   //insert price certificate
02911   return appendMixInfo_internal(elemPriceCert, WITH_SUBTREE);
02912 
02913 #endif
02914   return E_SUCCESS;
02915 }
02916 
02917 SINT32 CACmdLnOptions::setPaymentInstance(DOMElement *elemAccounting)
02918 {
02919 
02920 #ifdef PAYMENT
02921   DOMElement* elemJPI = NULL;
02922 
02923   if(elemAccounting == NULL) return E_UNKNOWN;
02924    ASSERT_ACCOUNTING_OPTIONS_PARENT
02925     (elemAccounting->getNodeName(), OPTIONS_NODE_PAYMENT_INSTANCE);
02926 
02927   CAMsg::printMsg(LOG_DEBUG, "Parsing JPI values.\n");
02928 
02929   getDOMChildByName(elemAccounting, OPTIONS_NODE_PAYMENT_INSTANCE, elemJPI, false);
02930   m_pBI = CAXMLBI::getInstance(elemJPI);
02931   if (m_pBI == NULL)
02932   {
02933     CAMsg::printMsg(LOG_CRIT,"Could not instantiate payment instance interface. Did you really want to compile the mix with payment support?\n");
02934     return E_UNKNOWN;
02935   }
02936 #endif
02937   return E_SUCCESS;
02938 }
02939 
02940 
02941 SINT32 CACmdLnOptions::setAccountingSoftLimit(DOMElement *elemAccounting)
02942 {
02943 
02944 #ifdef PAYMENT
02945   DOMElement* elemAISoftLimit = NULL;
02946   UINT32 tmp = 0;
02947 
02948   if(elemAccounting == NULL) return E_UNKNOWN;
02949   ASSERT_ACCOUNTING_OPTIONS_PARENT
02950     (elemAccounting->getNodeName(), OPTIONS_NODE_AI_SOFT_LIMIT);
02951 
02952   if (getDOMChildByName
02953       (elemAccounting, OPTIONS_NODE_AI_SOFT_LIMIT, elemAISoftLimit, false) != E_SUCCESS)
02954   {
02955     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_SOFT_LIMIT);
02956     return E_UNKNOWN;
02957   }
02958   if(getDOMElementValue(elemAISoftLimit, &tmp)==E_SUCCESS)
02959   {
02960     m_iPaymentSoftLimit = tmp;
02961   }
02962   else
02963   {
02964     //or better set default values?
02965     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_AI_SOFT_LIMIT);
02966     return E_UNKNOWN;
02967   }
02968 #endif
02969   return E_SUCCESS;
02970 }
02971 
02972 
02973 SINT32 CACmdLnOptions::setAccountingHardLimit(DOMElement *elemAccounting)
02974 {
02975 
02976 #ifdef PAYMENT
02977   DOMElement* elemAIHardLimit = NULL;
02978   UINT32 tmp = 0;
02979 
02980   if(elemAccounting == NULL) return E_UNKNOWN;
02981   ASSERT_ACCOUNTING_OPTIONS_PARENT
02982     (elemAccounting->getNodeName(), OPTIONS_NODE_AI_HARD_LIMIT);
02983 
02984   if (getDOMChildByName
02985       (elemAccounting, OPTIONS_NODE_AI_HARD_LIMIT, elemAIHardLimit, false) != E_SUCCESS)
02986   {
02987     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_HARD_LIMIT);
02988     return E_UNKNOWN;
02989   }
02990   if(getDOMElementValue(elemAIHardLimit, &tmp)==E_SUCCESS)
02991   {
02992     m_iPaymentHardLimit = tmp;
02993   }
02994   else
02995   {
02996     //or better set default values?
02997     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_AI_HARD_LIMIT);
02998     return E_UNKNOWN;
02999   }
03000 #endif
03001   return E_SUCCESS;
03002 }
03003 
03004 
03005 SINT32 CACmdLnOptions::setPrepaidInterval(DOMElement *elemAccounting)
03006 {
03007 
03008 #ifdef PAYMENT
03009   DOMElement* elemPrepaidIval = NULL;
03010   UINT32 tmp = 0;
03011 
03012   if(elemAccounting == NULL) return E_UNKNOWN;
03013   ASSERT_ACCOUNTING_OPTIONS_PARENT
03014     (elemAccounting->getNodeName(), OPTIONS_NODE_PREPAID_IVAL);
03015 
03016   if (getDOMChildByName
03017       (elemAccounting, OPTIONS_NODE_PREPAID_IVAL, elemPrepaidIval, false) != E_SUCCESS)
03018   {
03019     LOG_NODE_NOT_FOUND(OPTIONS_NODE_PREPAID_IVAL);
03020 
03021     if (getDOMChildByName
03022         (elemAccounting, OPTIONS_NODE_PREPAID_IVAL_KB, elemPrepaidIval, false) != E_SUCCESS)
03023     {
03024       LOG_NODE_NOT_FOUND(OPTIONS_NODE_PREPAID_IVAL_KB);
03025     }
03026     else
03027     {
03028       if(getDOMElementValue(elemPrepaidIval, &tmp)==E_SUCCESS)
03029       {
03030         m_iPrepaidInterval = tmp * 1000;
03031       }
03032     }
03033   }
03034   else if(getDOMElementValue(elemPrepaidIval, &tmp) == E_SUCCESS)
03035   {
03036     m_iPrepaidInterval = tmp;
03037   }
03038   else
03039   {
03040     CAMsg::printMsg(LOG_INFO,"Node \"%s\" is empty! Setting default...\n",
03041         OPTIONS_NODE_PREPAID_IVAL);
03042     m_iPrepaidInterval = OPTIONS_DEFAULT_PREPAID_IVAL;
03043   }
03044   if (m_iPrepaidInterval > OPTIONS_DEFAULT_PREPAID_IVAL )
03045   {
03046     CAMsg::printMsg(LOG_WARNING,"Prepaid interval is higher than %u! "
03047         "No JAP will pay more in advance!\n", OPTIONS_DEFAULT_PREPAID_IVAL);
03048   }
03049   else if (m_iPrepaidInterval < 5000)
03050   {
03051     CAMsg::printMsg(LOG_WARNING,"Prepaid interval of %u is far too low! "
03052         "Performance will be critical and clients will lose connection!\n", m_iPrepaidInterval);
03053   }
03054 
03055   //insert prepaid interval
03056   DOMElement* elemInterval = createDOMElement(m_docMixInfo, OPTIONS_NODE_PREPAID_IVAL_KB);
03057   setDOMElementValue(elemInterval, (m_iPrepaidInterval / 1000) );
03058   //TODO: handle exceptional cases */
03059   m_docMixInfo->getDocumentElement()->appendChild(elemInterval);
03060 #endif
03061   return E_SUCCESS;
03062 }
03063 
03064 
03065 SINT32 CACmdLnOptions::setSettleInterval(DOMElement *elemAccounting)
03066 {
03067 
03068 #ifdef PAYMENT
03069   DOMElement* elemSettleIval = NULL;
03070   UINT32 tmp = 0;
03071 
03072   if(elemAccounting == NULL) return E_UNKNOWN;
03073   ASSERT_ACCOUNTING_OPTIONS_PARENT
03074     (elemAccounting->getNodeName(), OPTIONS_NODE_SETTLE_IVAL);
03075 
03076   if (getDOMChildByName
03077       (elemAccounting, OPTIONS_NODE_SETTLE_IVAL, elemSettleIval, false) != E_SUCCESS)
03078   {
03079     LOG_NODE_NOT_FOUND(OPTIONS_NODE_SETTLE_IVAL);
03080     return E_UNKNOWN;
03081   }
03082   if(getDOMElementValue(elemSettleIval, &tmp)==E_SUCCESS)
03083   {
03084     m_iPaymentSettleInterval = tmp;
03085   }
03086   else
03087   {
03088     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_SETTLE_IVAL);
03089     return E_UNKNOWN;
03090   }
03091 #endif
03092   return E_SUCCESS;
03093 }
03094 
03095 
03096 SINT32 CACmdLnOptions::setAccountingDatabase(DOMElement *elemAccounting)
03097 {
03098 #ifdef PAYMENT
03099 
03100   DOMElement* elem = NULL;
03101   DOMElement* elemDatabase = NULL;
03102   UINT8 tmpBuff[TMP_BUFF_SIZE];
03103   UINT32 tmpLen = TMP_BUFF_SIZE, tmp = 0;
03104 
03105   /* DDB is only configured for first payment mix */
03106   if (!m_bFirstMix)
03107   {
03108     return E_SUCCESS;
03109   }
03110 
03111   if(elemAccounting == NULL) return E_UNKNOWN;
03112   ASSERT_ACCOUNTING_OPTIONS_PARENT
03113     (elemAccounting->getNodeName(), OPTIONS_NODE_AI_DB);
03114 
03115   CAMsg::printMsg(LOG_DEBUG, "Parsing AI values.\n");
03116 
03117   if (getDOMChildByName(elemAccounting, OPTIONS_NODE_AI_DB, elemDatabase, false) != E_SUCCESS)
03118   {
03119     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_DB);
03120     return E_UNKNOWN;
03121   }
03122 
03123   // get DB Hostname
03124   if (getDOMChildByName(elemDatabase, OPTIONS_NODE_AI_DB_HOST, elem, false) != E_SUCCESS)
03125   {
03126     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_DB_HOST);
03127     return E_UNKNOWN;
03128   }
03129 
03130   if(getDOMElementValue(elem, tmpBuff, &tmpLen) != E_SUCCESS)
03131   {
03132     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_AI_DB_HOST);
03133     return E_UNKNOWN;
03134   }
03135   strtrim(tmpBuff);
03136   m_strDatabaseHost = new UINT8[strlen((char*)tmpBuff)+1];
03137   strcpy((char *)m_strDatabaseHost, (char *) tmpBuff);
03138 
03139   // get Database Port
03140   if (getDOMChildByName
03141       (elemDatabase, OPTIONS_NODE_AI_DB_PORT, elem, false) != E_SUCCESS)
03142   {
03143     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_DB_PORT);
03144     return E_UNKNOWN;
03145   }
03146   if(getDOMElementValue(elem, &tmp) != E_SUCCESS)
03147   {
03148     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_AI_DB_PORT);
03149     return E_UNKNOWN;
03150   }
03151   m_iDatabasePort = tmp;
03152 
03153   // get DB Name
03154   if (getDOMChildByName
03155       (elemDatabase, OPTIONS_NODE_AI_DB_NAME, elem, false) != E_SUCCESS)
03156   {
03157     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_DB_NAME);
03158     return E_UNKNOWN;
03159   }
03160 
03161   tmpLen = TMP_BUFF_SIZE;
03162   memset(tmpBuff, 0, tmpLen);
03163 
03164   if(getDOMElementValue
03165       (elem, tmpBuff, &tmpLen) != E_SUCCESS)
03166   {
03167     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_AI_DB_NAME);
03168     return E_UNKNOWN;
03169   }
03170   strtrim(tmpBuff);
03171   m_strDatabaseName = new UINT8[strlen((char*)tmpBuff)+1];
03172   strcpy((char *)m_strDatabaseName, (char *) tmpBuff);
03173 
03174   // get DB Username
03175   if (getDOMChildByName
03176       (elemDatabase, OPTIONS_NODE_AI_DB_USER, elem, false) != E_SUCCESS)
03177   {
03178     LOG_NODE_NOT_FOUND(OPTIONS_NODE_AI_DB_USER);
03179     return E_UNKNOWN;
03180   }
03181 
03182   tmpLen = TMP_BUFF_SIZE;
03183   memset(tmpBuff, 0, tmpLen);
03184 
03185   if(getDOMElementValue
03186       (elem, tmpBuff, &tmpLen) != E_SUCCESS)
03187   {
03188     LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_AI_DB_USER);
03189     return E_UNKNOWN;
03190   }
03191   strtrim(tmpBuff);
03192   m_strDatabaseUser = new UINT8[strlen((char*)tmpBuff)+1];
03193   strcpy((char *)m_strDatabaseUser, (char *) tmpBuff);
03194 
03195   //get DB password from xml
03196   getDOMChildByName(elemDatabase, OPTIONS_NODE_AI_DB_PASSW, elem, false);
03197 
03198   tmpLen = TMP_BUFF_SIZE;
03199   memset(tmpBuff, 0, tmpLen);
03200 
03201   //read password from xml if given
03202   if(getDOMElementValue(elem, tmpBuff, &tmpLen) != E_SUCCESS)
03203   {
03204     //read password from stdin:
03205     UINT8 dbpass[500];
03206     dbpass[0] = 0;
03207     printf("Please enter password for postgresql user %s at %s: ",m_strDatabaseUser, m_strDatabaseHost);
03208     scanf("%400[^\n]%*1[\n]",(char*)dbpass);
03209     int len = strlen((char *)dbpass);
03210     if(len>0)
03211     {
03212       m_strDatabasePassword = new UINT8[len+1];
03213       strcpy((char *)m_strDatabasePassword, (char *)dbpass);
03214     }
03215     else
03216     {
03217       m_strDatabasePassword = new UINT8[1];
03218       m_strDatabasePassword[0] = '\0';
03219     }
03220   }
03221   else
03222   {
03223     strtrim(tmpBuff);
03224     m_strDatabasePassword = new UINT8[strlen((char*)tmpBuff)+1];
03225     strcpy((char *)m_strDatabasePassword, (char *) tmpBuff);
03226   }
03227   CAMsg::printMsg(LOG_DEBUG, "Accounting database information parsed successfully.\n");
03228   
03229   // just for testing the connection to the database
03230   if(CAAccountingDBInterface::init() != E_SUCCESS)
03231   {
03232     exit(EXIT_FAILURE);
03233   }
03234   CAAccountingDBInterface::cleanup();
03235   
03236 #endif
03237   return E_SUCCESS;
03238 }
03239 
03240 /***********************************
03241  * network option setter functions *
03242  ***********************************/
03243 SINT32 CACmdLnOptions::setNetworkOptions(DOMElement *elemRoot)
03244 {
03245   DOMElement* elemNetwork = NULL;
03246   if (getDOMChildByName
03247       (elemRoot, OPTIONS_NODE_NETWORK, elemNetwork, false) != E_SUCCESS)
03248   {
03249     LOG_NODE_NOT_FOUND(OPTIONS_NODE_NETWORK);
03250     return E_UNKNOWN;
03251   }
03252 
03253   return invokeOptionSetters
03254     (networkOptionSetters, elemNetwork, NETWORK_OPTIONS_NR);
03255 }
03256 
03257 SINT32 CACmdLnOptions::setInfoServices(DOMElement *elemNetwork)
03258 {
03259   UINT8 tmpBuff[TMP_BUFF_SIZE];
03260   UINT32 tmpLen = TMP_BUFF_SIZE;
03261   DOMElement* elemInfoServiceContainer=NULL;
03262 
03263   if(elemNetwork == NULL) return E_UNKNOWN;
03264   ASSERT_NETWORK_OPTIONS_PARENT
03265     (elemNetwork->getNodeName(), OPTIONS_NODE_INFOSERVICE_LIST);
03266 
03267   getDOMChildByName
03268     (elemNetwork, OPTIONS_NODE_INFOSERVICE_LIST, elemInfoServiceContainer,false);
03269   if (elemInfoServiceContainer == NULL)
03270   {
03271     // old configuration version <= 0.61
03272     DOMElement* elemInfoService=NULL;
03273     DOMElement* elemAllowReconfig=NULL;
03274     if (getDOMChildByName
03275         (elemNetwork, OPTIONS_NODE_INFOSERVICE, elemInfoService, false) != E_SUCCESS)
03276     {
03277       LOG_NODE_NOT_FOUND(OPTIONS_NODE_INFOSERVICE);
03278     }
03279     /* LERNGRUPPE: There might not be any InfoService configuration in the file, but in infoservices.xml, so check this */
03280     if(elemInfoService != NULL)
03281     {
03282       getDOMChildByName
03283         (elemInfoService, OPTIONS_NODE_ALLOW_AUTO_CONF, elemAllowReconfig, false);
03284       CAListenerInterface* isListenerInterface = CAListenerInterface::getInstance(elemInfoService);
03285       if (!isListenerInterface)
03286       {
03287         LOG_NODE_EMPTY_OR_INVALID(OPTIONS_NODE_INFOSERVICE);
03288       }
03289       else
03290       {
03291         m_addrInfoServicesSize = 1;
03292         m_addrInfoServices = new CAListenerInterface*[m_addrInfoServicesSize];
03293         m_addrInfoServices[0] = isListenerInterface;
03294         if(getDOMElementValue(elemAllowReconfig,tmpBuff,&tmpLen)==E_SUCCESS)
03295         {
03296           m_bAcceptReconfiguration = (strcmp("True",(char*)tmpBuff) == 0);
03297         }
03298       }
03299     }
03300   }
03301   else
03302     {
03303       // Refactored
03304       parseInfoServices(elemInfoServiceContainer);
03305     }
03306 
03307   return E_SUCCESS;
03308 }
03309 
03310 SINT32 CACmdLnOptions::setListenerInterfaces(DOMElement *elemNetwork)
03311 {
03312   DOMElement* elemListenerInterfaces=NULL;
03313 
03314   if(elemNetwork == NULL) return E_UNKNOWN;
03315   ASSERT_NETWORK_OPTIONS_PARENT
03316     (elemNetwork->getNodeName(), OPTIONS_NODE_LISTENER_INTERFACES);
03317 
03318   getDOMChildByName
03319     (elemNetwork, OPTIONS_NODE_LISTENER_INTERFACES, elemListenerInterfaces, false);
03320   m_arListenerInterfaces = CAListenerInterface::getInstance(
03321     elemListenerInterfaces, m_cnListenerInterfaces);
03322 
03323 #ifndef DYNAMIC_MIX
03324     /* LERNGRUPPE: ListenerInterfaces may be configured dynamically */
03325   if (m_cnListenerInterfaces == 0)
03326   {
03327     CAMsg::printMsg(LOG_CRIT, "No listener interfaces found!\n");
03328     return E_UNKNOWN;
03329   }
03330 #endif
03331   if(elemListenerInterfaces != NULL)
03332     {
03333       // import listener interfaces element; this is needed for cascade auto configuration
03334       // -- inserted by ronin <ronin2@web.de> 2004-08-16
03335     appendMixInfo_internal(elemListenerInterfaces, WITH_SUBTREE);
03336     }
03337 
03338   UINT32 i;
03339   SINT32 ret;
03340   CASocket** arrSocketsIn=new CASocket*[getListenerInterfaceCount()];
03341   for (i = 0; i < getListenerInterfaceCount(); i++)
03342   {
03343     arrSocketsIn[i] = NULL;
03344   }
03345 
03346   ret = createSockets(false, arrSocketsIn, getListenerInterfaceCount());
03347 
03348   for(i=0;i<getListenerInterfaceCount();i++)
03349   {
03350     if (arrSocketsIn[i] != NULL)
03351     {
03352       arrSocketsIn[i]->close();
03353       delete arrSocketsIn[i];
03354       arrSocketsIn[i] = NULL;
03355     }
03356   }
03357   delete[] arrSocketsIn;
03358   arrSocketsIn=NULL;
03359 
03360   
03361   if (ret != E_SUCCESS && ret != E_UNSPECIFIED && ret != E_SPACE)
03362   {
03363     CAMsg::printMsg(LOG_CRIT, "Could not listen on at least one of the specified interfaces. Please check if another running mix or server process is blocking the listen addresses, and if you have sufficient system rights.\n");
03364   }
03365 
03366   return ret;
03367 }
03368 
03369 
03370 SINT32 CACmdLnOptions::createSockets(bool a_bMessages, CASocket** a_sockets, UINT32 a_socketsLen)
03371 {
03372     if (a_socketsLen <= 0)
03373     {
03374       CAMsg::printMsg(LOG_CRIT,"Could not create any listener sockets as we have no space reserved for them. This seems to be an implementation bug.");
03375       return E_SPACE;
03376     }
03377 
03378 
03379     UINT32 aktSocket;
03380     UINT8 buff[255];
03381     SINT32 ret = E_UNKNOWN;
03382     UINT32 currentInterface;
03383     CASocketAddr* pAddr;
03384     UINT32* arrayVirtualPorts = new UINT32[a_socketsLen];
03385     UINT32 iVirtualPortsLen = 0;
03386     UINT32 iHiddenPortsLen = 0;
03387     UINT32* arrayHiddenPorts = new UINT32[a_socketsLen];
03388     
03389 
03390     aktSocket = -1;
03391     for(currentInterface=0;currentInterface < getListenerInterfaceCount(); currentInterface++)
03392       {
03393         CAListenerInterface* pListener=NULL;
03394         pListener=getListenerInterface(currentInterface+1);
03395         if(pListener==NULL)
03396         {
03397           CAMsg::printMsg(LOG_CRIT,"Error: Listener interface %d is invalid.\n", currentInterface+1);
03398           
03399           delete[] arrayVirtualPorts;
03400           delete[] arrayHiddenPorts;
03401           
03402           return E_UNKNOWN;
03403         }
03404         
03405         pAddr=pListener->getAddr();
03406         pAddr->toString(buff,255);
03407         
03408         if(pAddr->getType()==AF_INET)
03409         {
03410           if (pListener->isVirtual())
03411           {
03412             arrayVirtualPorts[iVirtualPortsLen] = ((CASocketAddrINet*)pAddr)->getPort();
03413             iVirtualPortsLen++;
03414           }
03415           else if (pListener->isHidden())
03416           {
03417             arrayHiddenPorts[iHiddenPortsLen] = ((CASocketAddrINet*)pAddr)->getPort();
03418             iHiddenPortsLen++;
03419           }
03420         }
03421         
03422         if(pListener->isVirtual())
03423         {
03424           delete pListener;
03425           pListener = NULL;
03426           delete pAddr;
03427           pAddr = NULL;
03428           continue;
03429         }
03430         aktSocket++;
03431         
03432         if (a_socketsLen < (aktSocket + 1))
03433         {
03434           CAMsg::printMsg(LOG_CRIT, 
03435             "Found %d listener sockets, but we have only reserved memory for %d sockets. This seems to be an implementation error in the code.\n", 
03436             (aktSocket + 1), a_socketsLen);
03437 
03438           delete[] arrayVirtualPorts;
03439           delete[] arrayHiddenPorts;
03440           delete pAddr;
03441           
03442           return E_SPACE;
03443         }
03444         
03445         ret = E_SUCCESS;
03446         a_sockets[aktSocket] = new CASocket();
03447         a_sockets[aktSocket]->create(pAddr->getType());
03448         a_sockets[aktSocket]->setReuseAddr(true);
03449         
03450         delete pListener;
03451         pListener = NULL;
03452 #ifndef _WIN32
03453         //we have to be a temporary superuser if port <1024...
03454         int old_uid=geteuid();
03455         if(pAddr->getType()==AF_INET&&((CASocketAddrINet*)pAddr)->getPort()<1024)
03456         {
03457           if(seteuid(0)==-1) //changing to root
03458           {
03459             CAMsg::printMsg(LOG_CRIT,"Setuid failed! We might not be able to listen on interface %d (%s) as we cannot change to the root user.\n",
03460                 currentInterface+1, buff);
03461           }
03462         }
03463 #endif
03464         ret=a_sockets[aktSocket]->listen(*pAddr);
03465         delete pAddr;
03466         pAddr = NULL;
03467 
03468         if(ret!=E_SUCCESS)
03469         {
03470           CAMsg::printMsg(LOG_CRIT,"Socket error while listening on interface %d (%s). Reason: %s (%i)\n",currentInterface+1, buff,
03471               GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
03472         }
03473 
03474 #ifndef _WIN32
03475         seteuid(old_uid);
03476 #endif
03477         if(ret!=E_SUCCESS)
03478         {
03479             delete[] arrayVirtualPorts;
03480             delete[] arrayHiddenPorts;
03481             return E_UNKNOWN;
03482         }
03483 
03484         if (a_bMessages)
03485         {
03486             CAMsg::printMsg(LOG_DEBUG,"Listening on Interface: %s\n",buff);
03487         }
03488       }
03489 
03490     if (ret == E_UNKNOWN)
03491     {
03492       CAMsg::printMsg(LOG_CRIT,"Could not find any valid (non-virtual) listener interface!\n");
03493     }
03494     else if (ret == E_SUCCESS)
03495     {
03496       for (UINT32 iHiddenPort = 0; iHiddenPort < iHiddenPortsLen; iHiddenPort++)
03497       {
03498         bool bVirtualFound = false;
03499         for (UINT32 iVirtualPort = 0; iVirtualPort < iVirtualPortsLen; iVirtualPort++)
03500         {
03501           if (arrayHiddenPorts[iHiddenPort] == arrayVirtualPorts[iVirtualPort])
03502           {
03503             bVirtualFound = true;
03504             arrayVirtualPorts[iVirtualPort] = 0;
03505           }
03506         }
03507         if (!bVirtualFound)
03508         {
03509           CAMsg::printMsg(LOG_CRIT,"No virtuel listener interface found for the hidden interface %d with port %d. Please remove the hidden interface, add the corresponding virtual interface or remove the 'hidden' attribute from the interface.\n", iHiddenPort, arrayHiddenPorts[iHiddenPort]);
03510           ret = E_UNSPECIFIED;
03511           break;
03512         }
03513       }
03514       
03515       if (ret == E_SUCCESS)
03516       {
03517         for (UINT32 iVirtualPort = 0; iVirtualPort < iVirtualPortsLen; iVirtualPort++)
03518         {
03519           if (arrayVirtualPorts[iVirtualPort] != 0)
03520           {
03521             CAMsg::printMsg(LOG_CRIT,"No hidden listener interface found for the virtual interface %d with port %d. Please remove the virtual interface, add the corresponding hidden interface or remove the 'virtual' attribute from the interface.\n", iVirtualPort, arrayVirtualPorts[iVirtualPort]);
03522             ret = E_UNSPECIFIED;
03523             break;
03524           }
03525         }
03526       }
03527     }
03528     
03529     if (ret == E_SUCCESS && a_bMessages)
03530     {
03531       CAMsg::printMsg(LOG_DEBUG,"Listening on all interfaces.\n");
03532     }
03533     
03534     delete[] arrayVirtualPorts;
03535     delete[] arrayHiddenPorts;
03536     arrayVirtualPorts = NULL;
03537 
03538     return ret;
03539 }
03540 
03541 
03542 /* Proxy settings and next mix settings */
03543 SINT32 CACmdLnOptions::setTargetInterfaces(DOMElement *elemNetwork)
03544 {
03545   UINT8 tmpBuff[TMP_BUFF_SIZE];
03546   UINT32 tmpLen = TMP_BUFF_SIZE;
03547   DOMElement* elemNextMix = NULL;
03548   DOMElement* elemProxies=NULL;
03549   TargetInterface* targetInterfaceNextMix = NULL;
03550   //get TargetInterfaces
03551   m_cnTargets=0;
03552 
03553   if(elemNetwork == NULL) return E_UNKNOWN;
03554   ASSERT_NETWORK_OPTIONS_PARENT
03555     (elemNetwork->getNodeName(), OPTIONS_NODE_NEXT_MIX);
03556 
03557   //NextMix --> only one!!
03558   getDOMChildByName
03559     (elemNetwork, OPTIONS_NODE_NEXT_MIX, elemNextMix, false);
03560   if(elemNextMix != NULL)
03561   {
03562     NetworkType type;
03563     CASocketAddr* addr = NULL;
03564     DOMElement* elemType = NULL;
03565     getDOMChildByName
03566       (elemNextMix, OPTIONS_NODE_NETWORK_PROTOCOL, elemType, false);
03567 
03568     bool bAddrIsSet = false;
03569 
03570     if(getDOMElementValue(elemType, tmpBuff, &tmpLen) == E_SUCCESS)
03571     {
03572       strtrim(tmpBuff);
03573       if(strcmp((char*)tmpBuff, "RAW/TCP") == 0)
03574       {
03575         type=RAW_TCP;
03576       }
03577       else if(strcmp((char*)tmpBuff, "RAW/UNIX") == 0)
03578       {
03579         type=RAW_UNIX;
03580       }
03581       else if(strcmp((char*)tmpBuff, "SSL/TCP") == 0)
03582       {
03583         type=SSL_TCP;
03584       }
03585       else if(strcmp((char*)tmpBuff, "SSL/UNIX") == 0)
03586       {
03587         type=SSL_UNIX;
03588       }
03589 
03590       if( (type == SSL_TCP) || (type == RAW_TCP) )
03591       {
03592         DOMElement* elemPort = NULL;
03593         DOMElement* elemHost = NULL;
03594           DOMElement* elemIP = NULL;
03595           UINT8 buffHost[TMP_BUFF_SIZE];
03596           UINT32 buffHostLen = TMP_BUFF_SIZE;
03597         UINT16 port;
03598         getDOMChildByName
03599           (elemNextMix, OPTIONS_NODE_PORT, elemPort, false);
03600         if(getDOMElementValue(elemPort,&port) == E_SUCCESS)
03601         {
03602           addr = new CASocketAddrINet;
03603           //bool bAddrIsSet=false;
03604           getDOMChildByName
03605             (elemNextMix, OPTIONS_NODE_HOST, elemHost, false);
03606           /* The rules for <Host> and <IP> are as follows:
03607             * 1. if <Host> is given and not empty take the <Host> value for the address of the next mix; if not go to 2
03608             * 2. if <IP> if given and not empty take <IP> value for the address of the next mix; if not goto 3.
03609             * 3. this entry for the next mix is invalid!*/
03610           if(elemHost != NULL)
03611           {
03612             if(getDOMElementValue(elemHost,buffHost,&buffHostLen)==E_SUCCESS &&
03613                 ((CASocketAddrINet*)addr)->setAddr(buffHost,port)==E_SUCCESS)
03614             {
03615               bAddrIsSet = true;
03616             }
03617           }
03618           if(!bAddrIsSet)//now try <IP>
03619           {
03620             getDOMChildByName(elemNextMix, OPTIONS_NODE_IP, elemIP, false);
03621             if(elemIP == NULL || getDOMElementValue(elemIP,buffHost,&buffHostLen) == E_SUCCESS)
03622             {
03623               ((CASocketAddrINet*)addr)->setAddr(buffHost,port);
03624               bAddrIsSet = true;
03625             }
03626           }
03627             CAMsg::printMsg(LOG_INFO, "Setting target interface: %s:%d\n", buffHost, port);
03628         }
03629       }
03630 #ifdef HAVE_UNIX_DOMAIN_PROTOCOL
03631       else if( (type == SSL_UNIX) || (type == RAW_UNIX) )
03632       {
03633         DOMElement* elemFile=NULL;
03634         getDOMChildByName(elemNextMix, OPTIONS_NODE_FILE, elemFile, false);
03635         tmpLen = TMP_BUFF_SIZE;
03636         if(getDOMElementValue(elemFile, tmpBuff, &tmpLen) == E_SUCCESS)
03637         {
03638           tmpBuff[tmpLen]=0;
03639           strtrim(tmpBuff);
03640           addr=new CASocketAddrUnix;
03641           if(((CASocketAddrUnix*)addr)->setPath((char*)tmpBuff) == E_SUCCESS)
03642           {
03643             bAddrIsSet = true;
03644           }
03645         }
03646       }
03647 #endif
03648     }
03649 
03650     if(bAddrIsSet)
03651     {
03652       targetInterfaceNextMix=new TargetInterface;
03653       targetInterfaceNextMix->target_type=TARGET_MIX;
03654       targetInterfaceNextMix->net_type=type;
03655       targetInterfaceNextMix->addr=addr->clone();
03656       m_cnTargets=1;
03657     }
03658 
03659     delete addr;
03660     addr = NULL;
03661   }
03662 
03663   //Next Proxies and visible adresses
03664   SINT32 ret;
03665   UINT8 buff[255];
03666   UINT32 buffLen = 255;
03667   CASocket* tmpSocket;
03668 
03669   clearVisibleAddresses();
03670   getDOMChildByName(elemNetwork, OPTIONS_NODE_PROXY_LIST, elemProxies, false);
03671   if(elemProxies != NULL)
03672   {
03673     DOMNodeList* nlTargetInterfaces=NULL;
03674     nlTargetInterfaces=getElementsByTagName(elemProxies, OPTIONS_NODE_PROXY);
03675     m_cnTargets+=nlTargetInterfaces->getLength();
03676 
03677     if(nlTargetInterfaces->getLength()>0)
03678     {
03679       m_arTargetInterfaces=new TargetInterface[m_cnTargets];
03680       UINT32 aktInterface=0;
03681       NetworkType type=UNKNOWN_NETWORKTYPE;
03682       UINT32 proxy_type=0;
03683       CASocketAddr* addr=NULL;
03684       UINT16 port;
03685       bool bHttpProxyFound = false;
03686       for(UINT32 i=0; i < nlTargetInterfaces->getLength(); i++)
03687       {
03688         delete addr;
03689         addr=NULL;
03690         DOMNode* elemTargetInterface=NULL;
03691         elemTargetInterface=nlTargetInterfaces->item(i);
03692         DOMElement* elemType;
03693         getDOMChildByName
03694           (elemTargetInterface, OPTIONS_NODE_NETWORK_PROTOCOL, elemType,false);
03695         tmpLen = TMP_BUFF_SIZE;
03696         if(getDOMElementValue(elemType,tmpBuff,&tmpLen)!=E_SUCCESS)
03697           continue;
03698         strtrim(tmpBuff);
03699         if(strcmp((char*)tmpBuff,"RAW/TCP") == 0)
03700         {
03701           type=RAW_TCP;
03702         }
03703         else if(strcmp((char*)tmpBuff,"RAW/UNIX") == 0)
03704         {
03705           type=RAW_UNIX;
03706         }
03707         else if(strcmp((char*)tmpBuff,"SSL/TCP") == 0)
03708         {
03709           type=SSL_TCP;
03710         }
03711         else if(strcmp((char*)tmpBuff,"SSL/UNIX") == 0)
03712         {
03713           type=SSL_UNIX;
03714         }
03715         else
03716         {
03717           continue;
03718         }
03719         //ProxyType
03720         elemType=NULL;
03721         getDOMChildByName
03722           (elemTargetInterface, OPTIONS_NODE_PROXY_TYPE, elemType, false);
03723         tmpLen = TMP_BUFF_SIZE;
03724         if(getDOMElementValue(elemType,tmpBuff,&tmpLen)!=E_SUCCESS)
03725           continue;
03726         strtrim(tmpBuff);
03727         if(strcmp((char*)tmpBuff,"SOCKS")==0)
03728         {
03729           proxy_type=TARGET_SOCKS_PROXY;
03730         }
03731         else if(strcmp((char*)tmpBuff,"HTTP")==0)
03732         {
03733           proxy_type=TARGET_HTTP_PROXY;
03734         }
03735         else
03736         {
03737           continue;
03738         }
03739 
03740         if( (type==SSL_TCP) || (type == RAW_TCP) )
03741         {
03742           DOMElement* elemPort;
03743           DOMElement* elemHost;
03744           getDOMChildByName
03745             (elemTargetInterface, OPTIONS_NODE_PORT, elemPort, false);
03746           if(getDOMElementValue(elemPort,&port)!=E_SUCCESS)
03747           {
03748             continue;
03749           }
03750           addr=new CASocketAddrINet;
03751           getDOMChildByName
03752             (elemTargetInterface, OPTIONS_NODE_HOST, elemHost, false);
03753           if(elemHost != NULL)
03754           {
03755             UINT8 buffHost[TMP_BUFF_SIZE];
03756             UINT32 buffHostLen = TMP_BUFF_SIZE;
03757             if(getDOMElementValue(elemHost, buffHost, &buffHostLen) != E_SUCCESS)
03758             {
03759               continue;
03760             }
03761             if(((CASocketAddrINet*)addr)->setAddr(buffHost, port) != E_SUCCESS)
03762             {
03763               continue;
03764             }
03765           }
03766           else
03767           {
03768             continue;
03769           }
03770         }
03771         else
03772 #ifdef HAVE_UNIX_DOMAIN_PROTOCOL
03773         {
03774           DOMElement* elemFile;
03775           getDOMChildByName
03776             (elemTargetInterface, OPTIONS_NODE_FILE, elemFile, false);
03777           tmpLen = TMP_BUFF_SIZE;
03778           if(getDOMElementValue(elemFile, tmpBuff, &tmpLen) != E_SUCCESS)
03779           {
03780             continue;
03781           }
03782           tmpBuff[tmpLen]=0;
03783           strtrim(tmpBuff);
03784           addr=new CASocketAddrUnix;
03785           if(((CASocketAddrUnix*)addr)->setPath((char*)tmpBuff) != E_SUCCESS)
03786           {
03787             continue;
03788           }
03789         }
03790 #else
03791           continue;
03792 #endif
03793 
03794 
03795 
03796         // check connection to proxy
03797         tmpSocket = new CASocket;
03798         tmpSocket->setRecvBuff(50000);
03799         tmpSocket->setSendBuff(5000);
03800         ret = tmpSocket->connect(*addr,LAST_MIX_TO_PROXY_CONNECT_TIMEOUT);
03801         if (ret != E_SUCCESS)
03802         {
03803           if (addr->toString(buff, buffLen) != E_SUCCESS)
03804           {
03805             buff[0] = 0;
03806           }
03807           if (ret != E_UNKNOWN)
03808           {
03809             CAMsg::printMsg(LOG_WARNING, "Could not connect to proxy %s! Reason: %s (%i) Please check if the proxy is running.\n",
03810                 buff, GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
03811           }
03812           else
03813           {
03814             CAMsg::printMsg(LOG_WARNING, "Could not connect to proxy %s! Please check if the proxy is running.\n", buff);
03815           }
03816         }
03817 
03818         if (ret == E_SUCCESS)
03819         {
03820           if (proxy_type == TARGET_HTTP_PROXY)
03821           {
03822             // TODO: we should not send an HTTP request to a non-existing address, for example to test:9999; if squid runs, we will get an HTTP error response
03823             //if(tmpSocket->sendTimeOut(pMixPacket->payload.data,payLen,LAST_MIX_TO_PROXY_SEND_TIMEOUT)==SOCKET_ERROR) ...
03824             // else ... tmpSocket->receive(pMixPacket->payload.data,PAYLOAD_SIZE);
03825             // if we get no response or an invalid response, we set ret = E_UNKNOWN
03826 
03827             bHttpProxyFound = true;
03828           }
03829           else if (proxy_type == TARGET_SOCKS_PROXY)
03830           {
03831             // TODO maybe there is also a possibility to check the response of the SOCKS proxy?
03832             m_bSocksSupport = true;
03833           }
03834         }
03835 
03836         tmpSocket->close();
03837         delete tmpSocket;
03838 
03839 
03840         if (ret == E_SUCCESS)
03841         {
03842           addVisibleAddresses(elemTargetInterface);
03843           m_arTargetInterfaces[aktInterface].net_type=type;
03844           m_arTargetInterfaces[aktInterface].target_type=proxy_type;
03845           m_arTargetInterfaces[aktInterface].addr=addr->clone();
03846           aktInterface++;
03847         }
03848 
03849 
03850         delete addr;
03851         addr=NULL;
03852       }
03853 
03854       if (!bHttpProxyFound)
03855       {
03856         CAMsg::printMsg(LOG_CRIT, "No valid HTTP proxy was specified! Please install and configure an HTTP proxy like Squid before starting the mix.\n");
03857         for (UINT32 i = 0; i < aktInterface; i++)
03858         {
03859           delete m_arTargetInterfaces[aktInterface].addr;
03860         }
03861 
03862 
03863         return E_UNKNOWN;
03864       }
03865 
03866       m_cnTargets=aktInterface;
03867     }
03868   } //end if elemProxies!=null
03869   //add NextMixInterface to the End of the List...
03870   if(targetInterfaceNextMix != NULL)
03871   {
03872     if(m_arTargetInterfaces == NULL)
03873     {
03874       m_cnTargets=0;
03875       m_arTargetInterfaces=new TargetInterface[1];
03876     }
03877     m_arTargetInterfaces[m_cnTargets].net_type=targetInterfaceNextMix->net_type;
03878     m_arTargetInterfaces[m_cnTargets].target_type=targetInterfaceNextMix->target_type;
03879     m_arTargetInterfaces[m_cnTargets++].addr=targetInterfaceNextMix->addr;
03880     delete targetInterfaceNextMix;
03881     targetInterfaceNextMix = NULL;
03882   }
03883   else if(m_arTargetInterfaces == NULL)
03884   {
03885     CAMsg::printMsg(LOG_CRIT, "Neither proxy nor next mix target interfaces are specified!\n");
03886     return E_UNKNOWN;
03887   }
03888 
03889   //Set Proxy Visible Addresses if Last Mix and given
03890   if(isLastMix() && (m_docMixInfo != NULL) )
03891   {
03892     DOMElement* elemMix = m_docMixInfo->getDocumentElement();
03893     if(elemMix != NULL)
03894     {
03895       DOMElement* elemProxies=createDOMElement(m_docMixInfo,"Proxies");
03896       if (m_bSocksSupport)
03897       {
03898         setDOMElementAttribute(elemProxies, "socks5Support", (UINT8*)"true");
03899       }
03900       DOMElement* elemProxy=createDOMElement(m_docMixInfo,"Proxy");
03901       DOMElement* elemVisAddresses=createDOMElement(m_docMixInfo,"VisibleAddresses");
03902       elemMix->appendChild(elemProxies);
03903       elemProxies->appendChild(elemProxy);
03904       elemProxy->appendChild(elemVisAddresses);
03905       for(UINT32 i=1;i<=getVisibleAddressesCount();i++)
03906       {
03907         UINT8 tmp[255];
03908         UINT32 tmplen=255;
03909         if(getVisibleAddress(tmp,tmplen,i)==E_SUCCESS)
03910         {
03911           DOMElement* elemVisAddress=createDOMElement(m_docMixInfo,"VisibleAddress");
03912           DOMElement* elemHost=createDOMElement(m_docMixInfo,"Host");
03913           elemVisAddress->appendChild(elemHost);
03914           setDOMElementValue(elemHost,tmp);
03915           elemVisAddresses->appendChild(elemVisAddress);
03916         }
03917       }
03918     }
03919   }
03920 
03921   return E_SUCCESS;
03922 }
03923 
03924 SINT32 CACmdLnOptions::setServerMonitoring(DOMElement *elemNetwork)
03925 {
03926 #ifdef SERVER_MONITORING
03927 
03928   UINT8 tmpBuff[TMP_BUFF_SIZE];
03929   UINT32 tmpLen = TMP_BUFF_SIZE;
03930 
03931   DOMElement* elemServerMonitoringRoot = NULL;
03932   DOMElement* elemServerMonitoringHost = NULL;
03933   DOMElement* elemServerMonitoringPort = NULL;
03934 
03935   if(elemNetwork == NULL) return E_UNKNOWN;
03936   ASSERT_NETWORK_OPTIONS_PARENT
03937     (elemNetwork->getNodeName(), OPTIONS_NODE_SERVER_MONITORING);
03938 
03939   m_strMonitoringListenerHost = NULL;
03940   m_iMonitoringListenerPort = 0xFFFF;
03941 
03942   if (getDOMChildByName
03943       (elemNetwork, OPTIONS_NODE_SERVER_MONITORING, elemServerMonitoringRoot,false) == E_SUCCESS)
03944   {
03945     if(getDOMChildByName
03946         (elemServerMonitoringRoot, OPTIONS_NODE_HOST, elemServerMonitoringHost, false) == E_SUCCESS)
03947     {
03948       if(getDOMElementValue(elemServerMonitoringHost,
03949                   (UINT8 *)tmpBuff,&tmpLen)==E_SUCCESS)
03950       {
03951         m_strMonitoringListenerHost = new char[tmpLen+1];
03952         strncpy(m_strMonitoringListenerHost, (const char*) tmpBuff, tmpLen);
03953         m_strMonitoringListenerHost[tmpLen] = 0;
03954       }
03955     }
03956     if(getDOMChildByName
03957         (elemServerMonitoringRoot, OPTIONS_NODE_PORT,
03958          elemServerMonitoringPort, false) == E_SUCCESS)
03959     {
03960       UINT16 port = 0xFFFF;
03961       if(getDOMElementValue(elemServerMonitoringPort, &port)==E_SUCCESS)
03962       {
03963         m_iMonitoringListenerPort = port;
03964       }
03965     }
03966 
03967     /* only non-local ListnerInterfaces are showed in Mix status info */
03968       if( (elemServerMonitoringRoot != NULL) &&
03969         (m_strMonitoringListenerHost != NULL))
03970       {
03971         if( (strncmp("localhost", m_strMonitoringListenerHost, 9) != 0) &&
03972           (strncmp("127.0.0.1", m_strMonitoringListenerHost, 9) != 0) )
03973         {
03974           appendMixInfo_internal(elemServerMonitoringRoot, WITH_SUBTREE);
03975         }
03976       }
03977   }
03978   else
03979   {
03980     CAMsg::printMsg(LOG_DEBUG, "Server Monitoring Config not found\n");
03981   }
03982 #endif /* SERVER_MONITORING */
03983   return E_SUCCESS;
03984 }
03985 
03986 /* Read Configuration of KeepAliveTraffic */
03987 SINT32 CACmdLnOptions::setKeepAliveTraffic(DOMElement *elemNetwork)
03988 {
03989   DOMElement* elemKeepAlive = NULL;
03990   DOMElement* elemKeepAliveSendInterval = NULL;
03991   DOMElement* elemKeepAliveRecvInterval = NULL;
03992 
03993   if(elemNetwork == NULL) return E_UNKNOWN;
03994   ASSERT_NETWORK_OPTIONS_PARENT
03995     (elemNetwork->getNodeName(), OPTIONS_NODE_SERVER_MONITORING);
03996 
03997   getDOMChildByName(elemNetwork, OPTIONS_NODE_KEEP_ALIVE, elemKeepAlive, false);
03998   getDOMChildByName(elemKeepAlive, OPTIONS_NODE_KEEP_ALIVE_SEND_IVAL, elemKeepAliveSendInterval, false);
03999   getDOMChildByName(elemKeepAlive, OPTIONS_NODE_KEEP_ALIVE_RECV_IVAL, elemKeepAliveRecvInterval, false);
04000   getDOMElementValue(elemKeepAliveSendInterval, m_u32KeepAliveSendInterval, KEEP_ALIVE_TRAFFIC_SEND_WAIT_TIME);
04001   getDOMElementValue(elemKeepAliveRecvInterval, m_u32KeepAliveRecvInterval, KEEP_ALIVE_TRAFFIC_RECV_WAIT_TIME);
04002   return E_SUCCESS;
04003 }
04004 
04005 
04006 /***************************************
04007  * ressource option setter function(s) *
04008  *         (delay options)             *
04009  ***************************************/
04010 SINT32 CACmdLnOptions::setRessourceOptions(DOMElement *elemRoot)
04011 {
04012 #if defined (DELAY_CHANNELS) ||defined(DELAY_USERS)||defined(DELAY_CHANNELS_LATENCY)
04014     //this is at the moment:
04015     //<Ressources>
04016     //<UnlimitTraffic></UnlimitTraffic>    #Number of bytes/packets without resource limitation
04017     //<BytesPerIntervall></BytesPerIntervall>   #upper limit of number of bytes/packets which are processed per channel/per user per time intervall
04018     //<Intervall></Intervall>  #duration of one intervall in ms
04019     //<Latency></Latency> #minimum Latency per channel in ms
04020     //</Ressources>
04021     CAMsg::printMsg(LOG_INFO,"Loading Parameters for traffic shaping / resource limitation....\n");
04022     UINT32 u32 = 0;
04023     DOMElement *elemRessources=NULL;
04024     DOMElement *elem = NULL;
04025 
04026     if(elemRoot == NULL)
04027     {
04028       return E_UNKNOWN;
04029     }
04030 
04031     getDOMChildByName(elemRoot, OPTIONS_NODE_RESSOURCES, elemRessources,false);
04032     if(elemRessources!=NULL)
04033     {
04034 #if defined (DELAY_CHANNELS) || defined(DELAY_USERS)
04035       if( getDOMChildByName
04036           (elemRessources, OPTIONS_NODE_UNLIMIT_TRAFFIC, elem, false) == E_SUCCESS &&
04037         getDOMElementValue(elem, &u32) == E_SUCCESS )
04038       {
04039         m_u32DelayChannelUnlimitTraffic = u32;
04040       }
04041       if( getDOMChildByName
04042           (elemRessources, OPTIONS_NODE_BYTES_PER_IVAL, elem, false) == E_SUCCESS &&
04043         getDOMElementValue(elem, &u32) == E_SUCCESS)
04044       {
04045         m_u32DelayChannelBucketGrow = u32;
04046       }
04047       if( getDOMChildByName
04048           (elemRessources, OPTIONS_NODE_DELAY_IVAL, elem, false) == E_SUCCESS &&
04049         getDOMElementValue(elem, &u32) == E_SUCCESS)
04050       {
04051         m_u32DelayChannelBucketGrowIntervall = u32;
04052       }
04053 #endif
04054 #if defined (DELAY_CHANNELS_LATENCY)
04055       if( getDOMChildByName
04056           (elemRessources, OPTIONS_NODE_LATENCY, elem, false) == E_SUCCESS &&
04057         getDOMElementValue(elem, &u32) == E_SUCCESS)
04058       {
04059         m_u32DelayChannelLatency = u32;
04060       }
04061 #endif
04062     }
04063 #endif
04064   return E_SUCCESS;
04065 }
04066 
04067 /*************************************************
04068  * terms and condition option setter function(s) *
04069  *************************************************/
04070 SINT32 CACmdLnOptions::setTermsAndConditions(DOMElement *elemRoot)
04071 {
04072   SINT32 ret = E_SUCCESS;
04073   DOMElement *elemTnCs = NULL;
04074 
04075   if(elemRoot == NULL)
04076   {
04077     return E_UNKNOWN;
04078   }
04079 
04080   ret = getDOMChildByName(elemRoot, OPTIONS_NODE_TNCS_OPTS, elemTnCs, true);
04081   if(elemTnCs != NULL)
04082   {
04083     return invokeOptionSetters
04084       (termsAndConditionsOptionSetters, elemTnCs, TERMS_AND_CONDITIONS_OPTIONS_NR);
04085   }
04086   else
04087   {
04088     CAMsg::printMsg(LOG_WARNING,"No Terms & Conditions for Operator specified!\n");
04089     return E_SUCCESS;
04090   }
04091 }
04092 
04093 SINT32 CACmdLnOptions::setTermsAndConditionsTemplates(DOMElement *elemTnCs)
04094 {
04095   if(elemTnCs == NULL)
04096   {
04097     CAMsg::printMsg(LOG_CRIT,"Terms And Conditions root element is null!\n");
04098     return E_UNKNOWN;
04099   }
04100   DOMElement *elemTnCsTemplates = NULL;
04101   DOMNodeList *templateList = NULL;
04102   bool nothingFound = true;
04103   getDOMChildByName(elemTnCs, OPTIONS_NODE_TNCS_TEMPLATES, elemTnCsTemplates);
04104 
04105   UINT8** loadedTemplateRefIds = NULL;
04106   bool templateError = false;
04107 
04108   if(elemTnCsTemplates != NULL)
04109   {
04110     templateList = getElementsByTagName(elemTnCsTemplates, OPTIONS_NODE_TNCS_TEMPLATE);
04111     if(templateList->getLength() > 0)
04112     {
04113       nothingFound = false;
04114       m_nrOfTermsAndConditionsTemplates = templateList->getLength();
04115       m_termsAndConditionsTemplates = new XERCES_CPP_NAMESPACE::DOMDocument*[m_nrOfTermsAndConditionsTemplates];
04116       loadedTemplateRefIds = new UINT8*[m_nrOfTermsAndConditionsTemplates];
04117       memset(loadedTemplateRefIds, 0, (sizeof(UINT8*)*m_nrOfTermsAndConditionsTemplates) );
04118 
04119       UINT8 currentTemplateURL[TMP_BUFF_SIZE];
04120       UINT32 len = TMP_BUFF_SIZE;
04121       memset(currentTemplateURL, 0, len);
04122 
04123       for (XMLSize_t i = 0; i < templateList->getLength(); i++)
04124       {
04125         getDOMElementValue(templateList->item(i), currentTemplateURL, &len);
04126         m_termsAndConditionsTemplates[i] = parseDOMDocument(currentTemplateURL);
04127         if(m_termsAndConditionsTemplates[i] == NULL)
04128         {
04129           CAMsg::printMsg(LOG_WARNING, "Cannot load Terms And Conditions template '%s'.\n",
04130               currentTemplateURL);
04131           return E_UNKNOWN;
04132         }
04133         UINT8* refId = getTermsAndConditionsTemplateRefId(m_termsAndConditionsTemplates[i]->getDocumentElement());
04134         if(refId != NULL)
04135         {
04136           loadedTemplateRefIds[i] = refId;
04137           for(XMLSize_t j = 0; j < i; j++)
04138           {
04139             if(strncmp((char *)refId, (char *) loadedTemplateRefIds[j], TEMPLATE_REFID_MAXLEN) == 0 )
04140             {
04141               templateError = true;
04142               CAMsg::printMsg(LOG_ERR, "duplicate Terms And Conditions template '%s'.\n",refId);
04143               break;
04144             }
04145           }
04146         }
04147         else
04148         {
04149           templateError = true;
04150           CAMsg::printMsg(LOG_ERR, "Terms And Conditions template with invalid refid found.\n");
04151           break;
04152         }
04153 
04154         if(!templateError)
04155         {
04156           CAMsg::printMsg(LOG_INFO, "loaded Terms And Conditions template '%s'.\n",refId);
04157         }
04158         else
04159         {
04160           break;
04161         }
04162         len = TMP_BUFF_SIZE;
04163       }
04164     }
04165     if(loadedTemplateRefIds != NULL)
04166     {
04167       for(XMLSize_t j = 0; j < m_nrOfTermsAndConditionsTemplates; j++)
04168       {
04169         delete [] loadedTemplateRefIds[j];
04170         loadedTemplateRefIds[j] = NULL;
04171       }
04172       delete [] loadedTemplateRefIds;
04173       loadedTemplateRefIds = NULL;
04174     }
04175     if(templateError)
04176     {
04177       return E_UNKNOWN;
04178     }
04179   }
04180 
04181   if(nothingFound)
04182   {
04183     CAMsg::printMsg(LOG_INFO,"No Terms And Conditions templates found.\n");
04184   }
04185 
04186   return E_SUCCESS;
04187 }
04188 SINT32 CACmdLnOptions::setTermsAndConditionsList(DOMElement *elemTnCs)
04189 {
04190   if(elemTnCs == NULL)
04191   {
04192     CAMsg::printMsg(LOG_CRIT,"Terms And Conditions root element is null!\n");
04193     return E_UNKNOWN;
04194   }
04195   DOMElement *elemTnCsList = NULL;
04196   getDOMChildByName(elemTnCs, OPTIONS_NODE_TNCS, elemTnCsList);
04197 
04198   if(elemTnCsList == NULL)
04199   {
04200     CAMsg::printMsg(LOG_CRIT,"No definitions for Terms And Conditions found!\n");
04201     return E_UNKNOWN;
04202   }
04203 
04204   UINT32 attrCheckLen = TMP_BUFF_SIZE;
04205   UINT8 attrCheck[TMP_BUFF_SIZE];
04206   memset(attrCheck, 0, attrCheckLen);
04207 
04208   UINT32 localeLen = TMP_LOCALE_SIZE;
04209   UINT8 locale[TMP_LOCALE_SIZE];
04210   memset(locale, 0, localeLen);
04211 
04212   UINT32 dateLen = TMP_DATE_SIZE;
04213   UINT8 date[TMP_DATE_SIZE];
04214   memset(date, 0, dateLen);
04215 
04216   if( (getDOMElementAttribute(elemTnCsList, OPTIONS_ATTRIBUTE_TNC_DATE, date, &dateLen) != E_SUCCESS) ||
04217     (strlen((char *)date) != ((TMP_DATE_SIZE) - 1) ) )
04218   {
04219     CAMsg::printMsg(LOG_CRIT,"Attribute '%s' is not properly set for the global definition of Terms And Conditions!\n",
04220         OPTIONS_ATTRIBUTE_TNC_DATE);
04221     return E_UNKNOWN;
04222   }
04223 
04224   m_docOpTnCs = createDOMDocument();
04225 
04226   DOMElement *currentTnCEntry = NULL;
04227   DOMNodeList *tncDefEntryList = getElementsByTagName(elemTnCsList, OPTIONS_NODE_TNCS_TRANSLATION);
04228 
04229   if(tncDefEntryList->getLength() < 1)
04230   {
04231     CAMsg::printMsg(LOG_CRIT,"No Terms And Conditions entries found!\n");
04232     return E_UNKNOWN;
04233   }
04234 
04235   DOMElement *tncTranslationImports = NULL;
04236   DOMElement *tncOperatorNode = NULL;
04237   getDOMChildByName(elemTnCsList, OPTIONS_NODE_TNCS_TRANSLATION_IMPORTS, tncTranslationImports, false);
04238   if(tncTranslationImports != NULL)
04239   {
04240     getDOMChildByName(tncTranslationImports, OPTIONS_NODE_TNCS_OPERATOR, tncOperatorNode, false);
04241   }
04242   bool defaultLangValue = false;
04243   bool defaultLangFound = false;
04244   bool operatorImportNodeFound = (tncOperatorNode != NULL);
04245 
04246   /* validity check for every definition: are all necessary attributes set (referenceId, locale), length ok
04247    * and is there EXACTLY ONE default language specified?
04248