pastebin - collaborative debugging tool
kpaste.net RSS


ZNC modified savebuff.cpp
Posted by Admin on Sun 7th Mar 2010 11:16
raw | new post

  1. /*
  2.  * Copyright (C) 2004-2010  See the AUTHORS file for details.
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify it
  5.  * under the terms of the GNU General Public License version 2 as published
  6.  * by the Free Software Foundation.
  7.  *
  8.  * Buffer Saving thing, incase your shit goes out while your out
  9.  * Author: imaginos <imaginos@imaginos.net>
  10.  *
  11.  * Its only as secure as your shell, the encryption only offers a slightly
  12.  * better solution then plain text.
  13.  */
  14.  
  15. #define REQUIRESSL
  16. #define LEGACY_SAVEBUFF
  17.  
  18. #include "Chan.h"
  19. #include "User.h"
  20. #include <sys/stat.h>
  21.  
  22. #define CRYPT_VERIFICATION_TOKEN "::__:SAVEBUFF:__::"
  23. // this is basically plain text, but so is having the pass in the command line so *shrug*
  24. // you could at least do something kind of cool like a bunch of unprintable text
  25. #define CRYPT_LAME_PASS "::__:NOPASS:__::"
  26. #define CRYPT_ASK_PASS "--ask-pass"
  27.  
  28. class CSaveBuff;
  29.  
  30. class CSaveBuffJob : public CTimer
  31. {
  32. public:
  33.         CSaveBuffJob(CModule* pModule, unsigned int uInterval, unsigned int uCycles, const CString& sLabel, const CString& sDescription)
  34.                 : CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
  35.  
  36.         virtual ~CSaveBuffJob() {}
  37.  
  38. protected:
  39.         virtual void RunJob();
  40. };
  41.  
  42. class CSaveBuff : public CModule
  43. {
  44. public:
  45.         MODCONSTRUCTOR(CSaveBuff)
  46.         {
  47.                 m_bBootError = false;
  48.                 m_bFirstLoad = false;
  49.         }
  50.         virtual ~CSaveBuff()
  51.         {
  52.                 if (!m_bBootError)
  53.                 {
  54.                         SaveBufferToDisk();
  55.                 }
  56.         }
  57.  
  58.         virtual bool OnLoad(const CString& sArgs, CString& sMessage)
  59.         {
  60.                 if( sArgs == CRYPT_ASK_PASS )
  61.                 {
  62.                         char *pPass = getpass( "Enter pass for savebuff: " );
  63.                         if( pPass )
  64.                                 m_sPassword = CBlowfish::MD5( pPass );
  65.                         else
  66.                         {
  67.                                 m_bBootError = true;
  68.                                 sMessage = "Nothing retrieved from console. aborting";
  69.                         }
  70.                 }
  71.                 else if( sArgs.empty() )
  72.                         m_sPassword = CBlowfish::MD5( CRYPT_LAME_PASS );
  73.                 else
  74.                         m_sPassword = CBlowfish::MD5(sArgs);
  75.  
  76.                 return( !m_bBootError );
  77.         }
  78.  
  79.         virtual void OnIRCConnected()
  80.         {
  81.                 // dropped this into here because there seems to have been a changed where the module is loaded before the channels.
  82.                 // this is a good trigger to tell it to backfill the channels
  83.                 if( !m_bFirstLoad )
  84.                 {
  85.                         m_bFirstLoad = true;
  86.                         AddTimer(new CSaveBuffJob(this, 60, 0, "SaveBuff", "Saves the current buffer to disk every 1 minute"));
  87.                         const vector<CChan *>& vChans = m_pUser->GetChans();
  88.                         for (u_int a = 0; a < vChans.size(); a++)
  89.                         {
  90.                                 if (!vChans[a]->KeepBuffer())
  91.                                         continue;
  92.  
  93.                                 if (!BootStrap(vChans[a]))
  94.                                 {
  95.                                         PutUser(":***!znc@znc.in PRIVMSG " + vChans[a]->GetName() + " :Failed to decrypt this channel, did you change the encryption pass?");
  96.                                 }
  97.                         }
  98.                 }
  99.         }
  100.  
  101.         bool BootStrap(CChan *pChan)
  102.         {
  103.                 CString sFile;
  104.                 if (DecryptChannel(pChan->GetName(), sFile))
  105.                 {
  106.                         if (!pChan->GetBuffer().empty())
  107.                                 return(true); // reloaded a module probably in this case, so just verify we can decrypt the file
  108.  
  109.                         VCString vsLines;
  110.                         VCString::iterator it;
  111.  
  112.                         sFile.Split("\n", vsLines);
  113.  
  114.                         for (it = vsLines.begin(); it != vsLines.end(); it++) {
  115.                                 CString sLine(*it);
  116.                                 sLine.Trim();
  117.                                 pChan->AddBuffer(sLine);
  118.                         }
  119.                 } else
  120.                 {
  121.                         m_sPassword = "";
  122.                         CUtils::PrintError("[" + GetModName() + ".so] Failed to Decrypt [" + pChan->GetName() + "]");
  123.                         return(false);
  124.                 }
  125.  
  126.                 return(true);
  127.         }
  128.  
  129.         void SaveBufferToDisk()
  130.         {
  131.                 if (!m_sPassword.empty())
  132.                 {
  133.                         const vector<CChan *>& vChans = m_pUser->GetChans();
  134.                         for (u_int a = 0; a < vChans.size(); a++)
  135.                         {
  136.                                 CString sPath = GetPath(vChans[a]->GetName());
  137.                                 CFile File(sPath);
  138.  
  139.                                 if (!vChans[a]->KeepBuffer()) {
  140.                                         File.Delete();
  141.                                         continue;
  142.                                 }
  143.  
  144.                                 const vector<CString> & vBuffer = vChans[a]->GetBuffer();
  145.  
  146.                                 CString sFile = CRYPT_VERIFICATION_TOKEN;
  147.  
  148.                                 for (u_int b = 0; b < vBuffer.size(); b++)
  149.                                 {
  150.                                                 sFile += vBuffer[b] + "\n";
  151.                                 }
  152.  
  153.                                 CBlowfish c(m_sPassword, BF_ENCRYPT);
  154.                                 sFile = c.Crypt(sFile);
  155.                                 if (!sPath.empty())
  156.                                 {
  157.                                         if (File.Open(O_WRONLY | O_CREAT | O_TRUNC, 0600)) {
  158.                                                 File.Chmod(0600);
  159.                                                 File.Write(sFile);
  160.                                         }
  161.                                         File.Close();
  162.                                 }
  163.                         }
  164.                 }
  165.                 else
  166.                 {
  167.                         PutModule( "Password is unset usually meaning the decryption failed. You can setpass to the appropriate pass and things should start working, or setpass to a new pass and save to reinstantiate" );
  168.                 }
  169.         }
  170.  
  171.         virtual void OnModCommand(const CString& sCmdLine)
  172.         {
  173.                 CString sCommand = sCmdLine.Token(0);
  174.                 CString sArgs    = sCmdLine.Token(1, true);
  175.  
  176.                 if (sCommand.Equals("setpass"))
  177.                 {
  178.                         PutModule("Password set to [" + sArgs + "]");
  179.                         m_sPassword = CBlowfish::MD5(sArgs);
  180.  
  181.                 } else if (sCommand.Equals("dumpbuff"))
  182.                 {
  183.                         CString sFile;
  184.                         if (DecryptChannel(sArgs, sFile))
  185.                         {
  186.                                 VCString vsLines;
  187.                                 VCString::iterator it;
  188.  
  189.                                 sFile.Split("\n", vsLines);
  190.  
  191.                                 for (it = vsLines.begin(); it != vsLines.end(); it++) {
  192.                                         CString sLine(*it);
  193.                                         sLine.Trim();
  194.                                         PutModule("[" + sLine + "]");
  195.                                 }
  196.                         }
  197.                         PutModule("//!-- EOF " + sArgs);
  198.                 } else if (sCommand.Equals("replay"))
  199.                 {
  200.                         Replay(sArgs);
  201.                         PutModule("Replayed " + sArgs);
  202.  
  203.                 } else if (sCommand.Equals("save"))
  204.                 {
  205.                         SaveBufferToDisk();
  206.                         PutModule("Done.");
  207.                 } else
  208.                         PutModule("Unknown command [" + sCommand + "]");
  209.         }
  210.  
  211.         void Replay(const CString & sChan)
  212.         {
  213.                 CString sFile;
  214.                 PutUser(":***!znc@znc.in PRIVMSG " + sChan + " :Buffer Playback...");
  215.                 if (DecryptChannel(sChan, sFile))
  216.                 {
  217.                         VCString vsLines;
  218.                         VCString::iterator it;
  219.  
  220.                         sFile.Split("\n", vsLines);
  221.  
  222.                         for (it = vsLines.begin(); it != vsLines.end(); it++) {
  223.                                 CString sLine(*it);
  224.                                 sLine.Trim();
  225.                                 PutUser(sLine);
  226.                         }
  227.                 }
  228.                 PutUser(":***!znc@znc.in PRIVMSG " + sChan + " :Playback Complete.");
  229.         }
  230.  
  231.         CString GetPath(const CString & sChannel)
  232.         {
  233.                 CString sBuffer = m_pUser->GetUserName() + sChannel.AsLower();
  234.                 CString sRet = GetSavePath();
  235.                 sRet += "/" + CBlowfish::MD5(sBuffer, true);
  236.                 return(sRet);
  237.         }
  238.  
  239. #ifdef LEGACY_SAVEBUFF /* event logging is deprecated now in savebuf. Use buffextras module along side of this */
  240.         CString SpoofChanMsg(const CString & sChannel, const CString & sMesg)
  241.         {
  242.                 CString sReturn = ":*" + GetModName() + "!znc@znc.in PRIVMSG " + sChannel + " :" + CString(time(NULL)) + " " + sMesg;
  243.                 return(sReturn);
  244.         }
  245.  
  246.         void AddBuffer(CChan& chan, const CString &sLine)
  247.         {
  248.                 // If they have keep buffer disabled, only add messages if no client is connected
  249.                 if (!chan.KeepBuffer() && m_pUser->IsUserAttached())
  250.                         return;
  251.                 chan.AddBuffer(sLine);
  252.         }
  253.  
  254.         virtual void OnRawMode(const CNick& cOpNick, CChan& cChannel, const CString& sModes, const CString& sArgs)
  255.         {
  256.                 AddBuffer(cChannel, SpoofChanMsg(cChannel.GetName(), cOpNick.GetNickMask() + " MODE " + sModes + " " + sArgs));
  257.         }
  258.         virtual void OnQuit(const CNick& cNick, const CString& sMessage, const vector<CChan*>& vChans)
  259.         {
  260.                 for (u_int a = 0; a < vChans.size(); a++)
  261.                 {
  262.                         AddBuffer(*vChans[a], SpoofChanMsg(vChans[a]->GetName(), cNick.GetNickMask() + " QUIT " + sMessage));
  263.                 }
  264.                 if (cNick.GetNick().Equals(m_pUser->GetNick()))
  265.                         SaveBufferToDisk(); // need to force a save here to see this!
  266.         }
  267.  
  268.         virtual void OnNick(const CNick& cNick, const CString& sNewNick, const vector<CChan*>& vChans)
  269.         {
  270.                 for (u_int a = 0; a < vChans.size(); a++)
  271.                 {
  272.                         AddBuffer(*vChans[a], SpoofChanMsg(vChans[a]->GetName(), cNick.GetNickMask() + " NICK " + sNewNick));
  273.                 }
  274.         }
  275.         virtual void OnKick(const CNick& cNick, const CString& sOpNick, CChan& cChannel, const CString& sMessage)
  276.         {
  277.                 AddBuffer(cChannel, SpoofChanMsg(cChannel.GetName(), sOpNick + " KICK " + cNick.GetNickMask() + " " + sMessage));
  278.         }
  279.         virtual void OnJoin(const CNick& cNick, CChan& cChannel)
  280.         {
  281.                 if (cNick.GetNick().Equals(m_pUser->GetNick()) && cChannel.GetBuffer().empty())
  282.                 {
  283.                         BootStrap((CChan *)&cChannel);
  284.                         if (!cChannel.GetBuffer().empty())
  285.                                 Replay(cChannel.GetName());
  286.                 }
  287.                 AddBuffer(cChannel, SpoofChanMsg(cChannel.GetName(), cNick.GetNickMask() + " JOIN"));
  288.         }
  289.         virtual void OnPart(const CNick& cNick, CChan& cChannel)
  290.         {
  291.                 AddBuffer(cChannel, SpoofChanMsg(cChannel.GetName(), cNick.GetNickMask() + " PART"));
  292.                 if (cNick.GetNick().Equals(m_pUser->GetNick()))
  293.                         SaveBufferToDisk(); // need to force a save here to see this!
  294.         }
  295.         virtual EModRet OnTopic (CNick &cNick, CChan  &cChannel, CString  &sTopic)
  296.         {
  297.                 AddBuffer(cChannel, SpoofChanMsg(cChannel.GetName(), cNick.GetNickMask() + " TOPIC :" + sTopic));
  298.                 return CONTINUE;
  299.         }
  300.  
  301. #endif /* LEGACY_SAVEBUFF */
  302.  
  303. private:
  304.         bool    m_bBootError;
  305.         bool    m_bFirstLoad;
  306.         CString m_sPassword;
  307.         bool DecryptChannel(const CString & sChan, CString & sBuffer)
  308.         {
  309.                 CString sChannel = GetPath(sChan);
  310.                 CString sFile;
  311.                 sBuffer = "";
  312.  
  313.                 CFile File(sChannel);
  314.  
  315.                 if (sChannel.empty() || !File.Open() || !File.ReadFile(sFile))
  316.                          return(true); // gonna be successful here
  317.  
  318.                 File.Close();
  319.  
  320.                 if (!sFile.empty())
  321.                 {
  322.                         CBlowfish c(m_sPassword, BF_DECRYPT);
  323.                         sBuffer = c.Crypt(sFile);
  324.  
  325.                         if (sBuffer.Left(strlen(CRYPT_VERIFICATION_TOKEN)) != CRYPT_VERIFICATION_TOKEN)
  326.                         {
  327.                                 // failed to decode :(
  328.                                 PutModule("Unable to decode Encrypted file [" + sChannel + "]");
  329.                                 return(false);
  330.                         }
  331.                         sBuffer.erase(0, strlen(CRYPT_VERIFICATION_TOKEN));
  332.                 }
  333.                 return(true);
  334.         }
  335. };
  336.  
  337.  
  338. void CSaveBuffJob::RunJob()
  339. {
  340.         CSaveBuff *p = (CSaveBuff *)m_pModule;
  341.         p->SaveBufferToDisk();
  342. }
  343.  
  344. MODULEDEFS(CSaveBuff, "Stores channel buffers to disk, encrypted")

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at