Changeset 546

Show
Ignore:
Timestamp:
05/03/06 03:05:12 (3 years ago)
Author:
oxff
Message:

nepenthes-experimental.log-irc: rewrote the processing code to be faster and actually readable, fixed formatting and added some possible TODOs

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • nepenthes/branches/nepenthes-experimental/modules/log-irc/IrcDialogue.cpp

    r543 r546  
    66 * 
    77 * Copyright (C) 2005  Paul Baecher & Markus Koetter 
     8 * Copyright (C) 2006  Georg Wicherski 
    89 *  
    910 * This program is free software; you can redistribute it and/or 
     
    6263 
    6364 
    64  
    65  
    66 /** 
    67  * Dialogue::Dialogue(Socket *) 
    68  * construktor for the IrcDialogue, creates a new IrcDialogue 
    69  *  
    70  * replies some crap to the socket 
    71  *  
    72  * @param socket the Socket the Dialogue has to use 
    73  */ 
    7465IrcDialogue::IrcDialogue(Socket *socket, LogIrc * logirc) 
    7566{ 
    7667        m_Socket = socket; 
    77     m_DialogueName = "IrcDialogue"; 
    78         m_DialogueDescription = "eXample Dialogue"; 
     68       m_DialogueName = "IrcDialogue"; 
     69        m_DialogueDescription = "IRC logging client"; 
    7970         
    8071        m_ConsumeLevel = CL_ASSIGN; 
     
    8576        if ( m_LogIrc->useTor() == true ) 
    8677        { 
    87                 socks4_header_t s4hHeader; 
    88                 memset(&s4hHeader,0,sizeof(socks4_header_t)); 
    89  
    90                 s4hHeader.ucVersion = 4; 
    91                 s4hHeader.ucCommand = 1; // connect request 
    92                 s4hHeader.usDestPort = htons(m_LogIrc->getIrcPort()); 
    93                 s4hHeader.ulDestAddr = m_LogIrc->getIrcIP(); 
    94  
    95                 m_Socket->doRespond((char *) &s4hHeader,8+ strlen(s4hHeader.szUser)+1 ); 
    96         } else 
     78                SocksHeader torHeader; 
     79                memset(&torHeader, 0, sizeof(torHeader)); 
     80 
     81                torHeader.version = 4; 
     82                torHeader.command = 1; // connect request 
     83                torHeader.destPort = htons(m_LogIrc->getIrcPort()); 
     84                torHeader.destAddress = m_LogIrc->getIrcIP(); 
     85 
     86                m_Socket->doRespond((char *) &torHeader,8+strlen(torHeader.user)+1); 
     87        } 
     88        else 
    9789        { 
    9890                m_State = IRCDIA_CONNECTED; 
     
    116108} 
    117109 
    118 /** 
    119  * Dialogue::incomingData(Message *) 
    120  *  
    121  * a small and ugly shell where we can use 
    122  * "download protocol://localction:port/path/to/file 
    123  * to trigger a download 
    124  *  
    125  * @param msg the Message the Socker received. 
    126  *  
    127  *  
    128  * @return CL_ASSIGN 
    129  */ 
    130110ConsumeLevel IrcDialogue::incomingData(Message *msg) 
    131111{ 
    132          
    133112        switch (m_State) 
    134113        { 
    135114        case IRCDIA_REQUEST_SEND: 
    136                 if ( ((socks4_header_t *)msg->getMsg())->ucCommand == 90 ) 
    137                 { 
    138                         logInfo("connected to ircd via tor\n"); 
     115                if( ((SocksHeader *) msg->getMsg())->command == 90 ) 
     116                { 
     117                        logInfo("Connected to IRC server \"%s\" through TOR proxy \"%s\"\n", m_LogIrc->getIrcServer().c_str(), m_LogIrc->getTorServer().c_str()); 
    139118                        m_State = IRCDIA_CONNECTED; 
    140119 
     
    143122                        sendUser(); 
    144123 
    145                 } else 
    146                 { 
    147                         logWarn("tor did not accept our connection \n"); 
     124                } 
     125                else 
     126                { 
     127                        logInfo("Relaying to IRC server \"%s\" denied by TOR proxy \"%s\"\n", m_LogIrc->getIrcServer().c_str(), m_LogIrc->getTorServer().c_str()); 
    148128                        return CL_DROP; 
    149129                } 
     130                 
    150131                break; 
     132                 
    151133        case IRCDIA_CONNECTED: 
    152                 { 
    153                         m_Buffer->add(msg->getMsg(),msg->getSize()); 
    154                         processBuffer(); 
    155                 } 
     134                m_Buffer->add(msg->getMsg(),msg->getSize()); 
     135                processBuffer(); 
     136                 
    156137                break; 
    157138 
    158139        } 
     140         
    159141        return CL_ASSIGN; 
    160142} 
    161143 
    162  
     144//! oxff: slightly faster and definitely better readable than old implementation 
    163145void IrcDialogue::processBuffer() 
    164146{ 
    165         logPF(); 
    166         unsigned char *linestart = (unsigned char *)m_Buffer->getData(); 
    167         unsigned char *linestopp = (unsigned char *)m_Buffer->getData(); 
    168  
    169         uint32_t i=0; 
    170         while (i < m_Buffer->getSize()) 
    171         { 
    172                  
    173                 if ( linestopp[i] == '\n') 
    174                 { 
    175                         i++; 
    176 //                      printf("IRCLINE len %i \n'%.*s'\n",(int32_t)(linestopp+i-linestart),(int32_t)(linestopp+i-linestart),linestart); 
    177                         string line((char *)m_Buffer->getData(),(int32_t)(linestopp+i - linestart));     
    178                         if (line[line.size()-1] == '\n') 
     147        uint32_t bufferLength = m_Buffer->getSize(); 
     148        uint32_t lineLength, processedLength; 
     149        const char * look, * lineStart; 
     150         
     151        if(bufferLength < 2) 
     152                return; 
     153                 
     154        processedLength = 0; 
     155        look = (char *) m_Buffer->getData(); 
     156         
     157        lineStart = look; 
     158        lineLength = 1; 
     159        ++look; 
     160         
     161        for(uint32_t i = 0; i < bufferLength; ++i, ++look) 
     162        { 
     163                if(* look == '\n' && * (look - 1) == '\r') 
     164                { 
     165                        // -1 cuts the already processed '\r' 
     166                        processLine(lineStart, lineLength - 1); 
     167                         
     168                        // + 1 includes the trailing '\n' 
     169                        processedLength += lineLength + 1; 
     170                        lineLength = 0; 
     171                        lineStart = look + 1; 
     172                } 
     173                else 
     174                        ++lineLength; 
     175        } 
     176         
     177        m_Buffer->cut(processedLength); 
     178
     179 
     180//! oxff: again slightly faster and definitely better readable 
     181//! oxff: now splits into IRC RFC elements, not words (leaving PRIVMSG lines) 
     182void  IrcDialogue::processLine(const char * line, uint32_t lineLength) 
     183
     184        vector<string> lineElements; 
     185         
     186        { 
     187                const char * look = line; 
     188                string element; 
     189                 
     190                if(* line == ':') 
     191                { 
     192                        if(!--lineLength) 
     193                                return; 
     194                                 
     195                        ++look; 
     196                } 
     197                 
     198                //! oxff: this is a pre-condition to the parsing loop 
     199                if(* look == ':') 
     200                { 
     201                        logWarn("IRC Server \"%s\" sent line beginning with two colons\n", m_LogIrc->getIrcServer().c_str()); 
     202                        return; 
     203                } 
     204 
     205                for(uint32_t i = 0; i < lineLength; ++i, ++look) 
     206                { 
     207                        if(* look == ' ') 
    179208                        { 
    180                                 line[line.size()-1] = '\0'; 
     209                                lineElements.push_back(element); 
     210                                element.erase(); 
    181211                        } 
    182                         if (line[line.size()-2] == '\r') 
    183                         { 
    184                                 line[line.size()-2] = '\0'; 
     212                        else if(* look == ':' && * (look - 1) == ' ') // look behind allowed due to pre-condition 
     213                        {                                
     214                                element = string(look + 1, lineLength - i - 1); 
     215                                lineElements.push_back(element); 
     216                                element.erase(); 
     217                                 
     218                                break; 
    185219                        } 
    186                         printf("test '%s'\n",line.c_str()); 
    187                         processLine(&line); 
    188                         m_Buffer->cut(i); 
    189                         i=0; 
    190                         linestart = linestopp+i; 
    191                 }else 
    192                 { 
    193                         i++; 
    194                 } 
    195         } 
    196 
    197  
    198 void IrcDialogue::processLine(string *line) 
    199 
    200         vector<string> words; 
    201  
    202         uint32_t i=0;       
    203         bool haschar = false; 
    204         uint32_t wordstart=0; 
    205         uint32_t wordstopp=0; 
    206  
    207         while ( i<=line->size() ) 
    208         { 
    209                 if ( ( ( (*line)[i] == ' ' || (*line)[i] == '\0') && haschar == true) ) 
    210                 { 
    211                         wordstopp = i; 
    212                         string word = line->substr(wordstart,wordstopp-wordstart); 
    213 //                      logInfo("Word is %i %i '%s' \n",wordstart,wordstopp,word.c_str()); 
    214                         words.push_back(word); 
    215                         haschar = false; 
    216                 } else 
    217                 if ( isgraph((*line)[i]) && haschar == false ) 
    218                 { 
    219                         haschar = true; 
    220                         wordstart = i; 
    221                 } 
    222                 i++; 
    223         } 
    224  
    225 /* 
    226         for (i=0;i<words.size();i++) 
    227         { 
    228                 logSpam("word is '%s'\n",words[i].c_str()); 
    229         } 
    230 */ 
    231  
    232         if (words[0] == "PING" ) 
    233         { 
    234                 string reply = "PONG "; 
    235                 reply += words[1]; 
    236                 reply += "\r\n"; 
    237                 m_Socket->doRespond((char *)reply.c_str(),reply.size()); 
    238  
    239         }else 
    240         if ( words[1] == "376" || words[1] == "422" ) 
    241         { 
    242                 string reply = "JOIN "; 
    243                 reply += m_LogIrc->getIrcChannel(); 
    244                 reply += " "; 
    245                 reply += m_LogIrc->getIrcChannelPass(); 
    246                 reply += "\r\n"; 
    247                 m_Socket->doRespond((char *)reply.c_str(),reply.size()); 
    248                 m_LogIrc->setDialogue(this); 
    249         }else 
    250         if (words[1] == "PONG" ) 
    251         { 
     220                        else 
     221                                element.push_back(* look); 
     222                } 
     223                 
     224                if(element.size())               
     225                        lineElements.push_back(element); 
     226        } 
     227         
     228        if(lineElements.empty()) 
     229                return; 
     230         
     231         
     232        if(lineElements.size() >= 1 && lineElements[1] == "433") 
     233                sendNick(true); 
     234        if(lineElements[0] == "PING" && lineElements.size() == 2) 
     235        { 
     236                string reply = "PONG " + lineElements[1] + "\r\n"; 
     237                 
     238                m_Socket->doRespond((char *) reply.data(), reply.size()); 
     239        } 
     240        else if(lineElements[0] == "PONG") 
    252241                m_Pinged = false; 
    253         }else 
    254         if ( words[1] == "433" ) 
    255         { 
    256                 sendNick(true); 
    257         }else 
    258         if ( words.size() >= 4 && words[1] == "PRIVMSG" && words[3] == ":!version") 
    259         { 
    260                 char *reply; 
    261                 asprintf(&reply,"PRIVMSG %s :Nepenthes Version %s  - Compiled on %s %s with %s %s \n",words[2].c_str(),VERSION,__DATE__, __TIME__,MY_COMPILER,__VERSION__); 
    262                 m_Socket->doRespond((char *)reply,strlen(reply)); 
    263                 free(reply); 
    264         } 
    265         return; 
    266  
    267 
    268  
    269 /** 
    270  * Dialogue::outgoingData(Message *) 
    271  * as we are not interested in these socket actions  
    272  * we simply return CL_DROP to show the socket 
    273  *  
    274  * @param msg 
    275  *  
    276  * @return CL_DROP 
    277  */ 
     242        else if(lineElements.size() >= 2 && (lineElements[1] == "003" ||lineElements[1] == "004" ||  lineElements[1] == "005" || lineElements[1] == "376" || lineElements[1] == "422")) 
     243                loggedOn(); 
     244        else if(lineElements.size() >= 4 && (lineElements[1] == "PRIVMSG" || lineElements[1] == "NOTICE")) 
     245                processMessage(lineElements[0].c_str(), lineElements[2].c_str(), lineElements[3].c_str()); 
     246
     247 
     248void IrcDialogue::processMessage(const char * origin, const char * target, const char * message) 
     249
     250        string responseMessage = string("PRIVMSG "); 
     251         
     252        logDebug("<%s.%s.%s> \"%s\"\n", m_LogIrc->getIrcServer().c_str(), target, origin, message); 
     253         
     254        if(m_NickName == target) 
     255        { 
     256                string originString = origin; 
     257                 
     258                responseMessage += originString.substr(0, originString.find('!')); 
     259        } 
     260        else 
     261                responseMessage += target; 
     262                 
     263        if(string(message) == "!version") 
     264        { 
     265                responseMessage += " :nepenthes v" VERSION " compiled on [" __DATE__ " " __TIME__ "] with " MY_COMPILER " " __VERSION__ "\r\n"; 
     266                m_Socket->doRespond((char *) responseMessage.data(), responseMessage.size()); 
     267        } 
     268         
     269
     270 
     271 
     272// TODO: add on-connect cmd to auth at nickserv 
     273 
     274void IrcDialogue::loggedOn() 
     275
     276        string joinCommand = "JOIN " + m_LogIrc->getIrcChannel() + " " + m_LogIrc->getIrcChannelPass() + "\r\n"; 
     277        m_Socket->doRespond((char *) joinCommand.data(), joinCommand.size()); 
     278
     279 
    278280ConsumeLevel IrcDialogue::outgoingData(Message *msg) 
    279281{ 
     
    281283} 
    282284 
    283 /** 
    284  * Dialogue::handleTimeout(Message *) 
    285  * as we are not interested in these socket actions  
    286  * we simply return CL_DROP to show the socket 
    287  *  
    288  * @param msg 
    289  *  
    290  * @return CL_DROP 
    291  */ 
    292285ConsumeLevel IrcDialogue::handleTimeout(Message *msg) 
    293286{ 
     
    295288        { 
    296289                m_Pinged = true; 
    297         string ping = "PING :12356789\r\n"; 
    298                 m_Socket->doRespond((char *)ping.c_str(),ping.size()); 
     290                 
     291                string ping = "PING :12356789\r\n"; 
     292                m_Socket->doRespond((char *) ping.data(), ping.size()); 
     293                 
    299294                return CL_ASSIGN; 
    300         }else 
     295        } 
     296        else 
    301297        { 
    302298                m_LogIrc->doRestart(); 
    303299                return CL_DROP; 
    304300        } 
    305  
    306 
    307  
    308 /** 
    309  * Dialogue::connectionLost(Message *) 
    310  * as we are not interested in these socket actions  
    311  * we simply return CL_DROP to show the socket 
    312  *  
    313  * @param msg 
    314  *  
    315  * @return CL_DROP 
    316  */ 
     301
     302 
    317303ConsumeLevel IrcDialogue::connectionLost(Message *msg) 
    318304{ 
    319305        logPF(); 
     306         
    320307        m_LogIrc->doRestart(); 
    321308        return CL_DROP; 
    322309} 
    323310 
    324 /** 
    325  * Dialogue::connectionShutdown(Message *) 
    326  * as we are not interested in these socket actions  
    327  * we simply return CL_DROP to show the socket 
    328  *  
    329  * @param msg 
    330  *  
    331  * @return CL_DROP 
    332  */ 
    333311ConsumeLevel IrcDialogue::connectionShutdown(Message *msg) 
    334312{ 
    335313        logPF(); 
     314         
    336315        m_LogIrc->doRestart(); 
    337316        return CL_DROP; 
    338317} 
     318 
     319 
     320 
     321// TODO: format, translate 
    339322 
    340323struct FlagMapping 
     
    343326        char    *m_ColorFlag; 
    344327}; 
    345  
    346328 
    347329const struct FlagMapping colors[] = 
     
    370352 
    371353 
    372  
    373 void    IrcDialogue::logIrc(uint32_t mask, const char *message) 
     354// TODO: parse log tags from configuration 
     355 
     356void IrcDialogue::logIrc(uint32_t mask, const char *message) 
    374357{ 
    375358        if ( 
     
    403386void IrcDialogue::sendNick(bool random) 
    404387{ 
    405         if (random) 
    406         { 
    407                 string nick = "NICK "; 
    408                 nick += m_LogIrc->getIrcNick(); 
    409                 nick += (char) ((int32_t)rand()%20 + 97); 
    410                 nick += "\r\n"; 
    411  
    412                 m_Socket->doRespond((char *)nick.c_str(),nick.size()); 
    413         }else 
    414         { 
    415                 string nick = "NICK "; 
    416                 nick += m_LogIrc->getIrcNick(); 
    417                 nick += "\r\n"; 
    418  
    419                 m_Socket->doRespond((char *)nick.c_str(),nick.size()); 
    420         } 
     388        m_NickName = m_LogIrc->getIrcNick(); 
     389         
     390        if(random) 
     391        { 
     392                m_NickName += "-"; 
     393                m_NickName += (char) ((int32_t)rand()%20 + 97); 
     394                m_NickName += (char) ((int32_t)rand()%20 + 97); 
     395                m_NickName += (char) ((int32_t)rand()%20 + 97); 
     396        } 
     397         
     398        string nickCommand = "NICK " + m_NickName + "\r\n"; 
     399        m_Socket->doRespond((char *) nickCommand.data(), nickCommand.size()); 
    421400} 
    422401 
    423402void IrcDialogue::sendUser() 
    424403{ 
    425         string user = "USER "; 
    426         user += m_LogIrc->getIrcIdent(); 
    427         user += " 0 0 :"; 
    428         user += m_LogIrc->getIrcUserInfo(); 
    429         user += "\r\n"; 
    430  
    431         m_Socket->doRespond((char *)user.c_str(),user.size()); 
     404        string user = "USER " + m_LogIrc->getIrcIdent() + " 0 0 :" + m_LogIrc->getIrcUserInfo() + "\r\n"; 
     405        m_Socket->doRespond((char *) user.data(), user.size()); 
    432406} 
    433407 
     
    436410        if ( m_LogIrc->getIrcPass().size() > 0 ) 
    437411        { 
    438         string pass = "PASS "; 
    439                 pass += m_LogIrc->getIrcPass(); 
    440                 pass += "\r\n"; 
    441                 m_Socket->doRespond((char *)pass.c_str(),pass.size()); 
    442         } 
    443 
    444  
     412                string pass = "PASS " + m_LogIrc->getIrcPass() + pass + "\r\n"; 
     413                m_Socket->doRespond((char *) pass.data(), pass.size()); 
     414        } 
     415
     416 
  • nepenthes/branches/nepenthes-experimental/modules/log-irc/IrcDialogue.hpp

    r378 r546  
    66 * 
    77 * Copyright (C) 2005  Paul Baecher & Markus Koetter 
     8 * Copyright (C) 2005  Georg Wicherski 
    89 *  
    910 * This program is free software; you can redistribute it and/or 
     
    3839using namespace std; 
    3940 
     41 
    4042namespace nepenthes 
    4143{ 
    42         typedef struct 
     44        struct SocksHeader 
    4345        { 
    44                 unsigned char ucVersion; 
    45                 unsigned char ucCommand; 
    46                 uint16_t usDestPort; 
    47                 uint32_t ulDestAddr
    48                 char szUser[1024]; 
     46                unsigned char version; 
     47                unsigned char command; 
     48                uint16_t destPort; 
     49                uint32_t destAddress
     50                char user[1024]; 
    4951 
    50         } socks4_header_t
     52        }
    5153 
    5254 
    53         typedef enum  
     55        enum IrcDialogueState 
    5456        { 
    5557                IRCDIA_REQUEST_SEND, 
    5658                IRCDIA_CONNECTED, 
    57         } irc_dia_state
     59        }
    5860 
    5961        class LogIrc; 
     
    6567                IrcDialogue(Socket *socket, LogIrc * logirc); 
    6668                ~IrcDialogue(); 
    67                 ConsumeLevel incomingData(Message *msg); 
    68                 ConsumeLevel outgoingData(Message *msg); 
    69                 ConsumeLevel handleTimeout(Message *msg); 
    70                 ConsumeLevel connectionLost(Message *msg); 
    71                 ConsumeLevel connectionShutdown(Message *msg); 
     69                 
     70                ConsumeLevel incomingData(Message * msg); 
     71                ConsumeLevel outgoingData(Message * msg); 
     72                ConsumeLevel handleTimeout(Message * msg); 
     73                ConsumeLevel connectionLost(Message * msg); 
     74                ConsumeLevel connectionShutdown(Message * msg); 
    7275 
    73                 void   logIrc(uint32_t mask, const char *message); 
     76                void logIrc(uint32_t mask, const char * message); 
    7477 
    7578                void sendNick(bool random); 
    7679                void sendUser(); 
    7780                void sendServerPass(); 
     81                 
    7882        protected: 
    79  
    8083                void processBuffer(); 
    81                 void processLine(string *line); 
     84                void processLine(const char * line, uint32_t lineLength); 
     85                 
     86                void loggedOn(); 
     87                void processMessage(const char * origin, const char * target, const char * message); 
     88                 
    8289                bool m_Pinged; 
     90                 
    8391                LogIrc  *m_LogIrc; 
    8492 
    85                 irc_dia_state m_State; 
     93                IrcDialogueState m_State; 
    8694 
    8795                string  m_NickName; 
  • nepenthes/branches/nepenthes-experimental/modules/log-irc/log-irc.conf.dist

    r330 r546  
    2121            nick        "nep-noname"; 
    2222            ident       "nepenthes"; 
    23             userinfo    "http://nepenthes.sf.net"; 
     23            userinfo    "http://nepenthes.mwcollect.org/"; 
    2424            usermodes   "+i"; 
    2525        }; 
  • nepenthes/branches/nepenthes-experimental/modules/log-irc/log-irc.cpp

    r543 r546  
    66 * 
    77 * Copyright (C) 2005  Paul Baecher & Markus Koetter 
     8 * Copyright (C) 2005  Georg Wicherski 
    89 *  
    910 * This program is free software; you can redistribute it and/or 
     
    7980{ 
    8081        m_ModuleName        = "log-irc"; 
    81         m_ModuleDescription = "log to irc using tor"; 
     82        m_ModuleDescription = "log to irc (optionally using tor)"; 
    8283        m_ModuleRevision    = "$Rev$"; 
    8384        m_Nepenthes = nepenthes; 
     
    291292} 
    292293 
     294string LogIrc::getTorServer() 
     295{ 
     296        return m_TorServer; 
     297} 
     298 
     299string LogIrc::getIrcServer() 
     300{ 
     301        return m_IrcServer; 
     302} 
     303 
    293304uint32_t LogIrc::getIrcIP() 
    294305{ 
  • nepenthes/branches/nepenthes-experimental/modules/log-irc/log-irc.hpp

    r378 r546  
    66 * 
    77 * Copyright (C) 2005  Paul Baecher & Markus Koetter 
     8 * Copyright (C) 2006  Georg Wicherski 
    89 *  
    910 * This program is free software; you can redistribute it and/or 
     
    5859        public: 
    5960                LogIrc(Nepenthes *); 
    60 //              LogIrc(LogHandler *lm); 
    6161                ~LogIrc(); 
    6262                Dialogue *createDialogue(Socket *socket); 
     
    6464                bool Exit(); 
    6565 
    66         bool dnsResolved(DNSResult *result); 
     66               bool dnsResolved(DNSResult *result); 
    6767                bool dnsFailure(DNSResult *result); 
    6868 
     
    8484                string getIrcChannelPass(); 
    8585                string getIrcUserModes(); 
    86                 string getIrcPass(); //server password 
     86                string getIrcPass(); 
     87                 
     88                string getTorServer(); 
     89                string getIrcServer(); 
    8790 
    8891