Advertisement
knarzling

fish znc-git/1.5

Nov 24th, 2014
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 23.14 KB | None | 0 0
  1. #include <znc/main.h>
  2. #include <znc/User.h>
  3. #include <znc/Nick.h>
  4. #include <znc/Modules.h>
  5. #include <znc/Chan.h>
  6. #include <znc/IRCNetwork.h>
  7.  
  8. #include <string.h>
  9. using std::vector;
  10. using std::pair;
  11. using std::map;
  12.  
  13. #include <netinet/in.h>
  14.  
  15. #include <openssl/opensslv.h>
  16. #include <openssl/blowfish.h>
  17.  
  18. #define REQUIRESSL  1
  19.  
  20. #if (OPENSSL_VERSION_NUMBER < 0x0090800f)
  21. #error "We require openssl >= 0.9.8"
  22. #endif
  23.  
  24. /*
  25.     Public Base64 conversion tables
  26. */
  27. unsigned char B64ABC[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  28. unsigned char b64buf[256];
  29.  
  30.  
  31. /*
  32.     void initb64();
  33.     Initializes the base64->base16 conversion tab.
  34.     Call this function once when your program starts.
  35.     and always after your B64 table has been changed.
  36. */
  37. void initb64(){
  38.     unsigned int i;
  39.     for (i=0; i<256; i++) b64buf[i]=0x00;
  40.     for (i=0; i<64; i++) b64buf[(B64ABC[i])]=i;
  41. }
  42.  
  43. /*
  44.    int b64toh(lpBase64String, lpDestinationBuffer);
  45.    Converts base64 string b to hexnumber d.
  46.    Returns size of hexnumber in bytes.
  47. */
  48. int b64toh(char *b, char *d){
  49.     int i,k,l;
  50.  
  51.     l=strlen(b);
  52.     if (l<2) return 0;
  53.     for (i=l-1;i>-1;i--){
  54.         if (b64buf[(unsigned char)(b[i])]==0) l--;
  55.         else break;
  56.     }
  57.  
  58.     if (l<2) return 0;
  59.     i=0, k=0;
  60.     while (1) {
  61.         i++;
  62.         if (k+1<l) d[i-1]=((b64buf[(unsigned char)(b[k])])<<2);
  63.         else break;
  64.         k++;
  65.         if (k<l) d[i-1]|=((b64buf[(unsigned char)(b[k])])>>4);
  66.         else break;
  67.         i++;
  68.         if (k+1<l) d[i-1]=((b64buf[(unsigned char)(b[k])])<<4);
  69.         else break;
  70.         k++;
  71.         if (k<l) d[i-1]|=((b64buf[(unsigned char)(b[k])])>>2);
  72.         else break;
  73.         i++;
  74.         if (k+1<l) d[i-1]=((b64buf[(unsigned char)(b[k])])<<6);
  75.         else break;
  76.         k++;
  77.         if (k<l) d[i-1]|=(b64buf[(unsigned char)(b[k])]);
  78.         else break;
  79.         k++;
  80.     }
  81.     return i-1;
  82. }
  83.  
  84. /*
  85.    int htob64(lpHexNumber, lpDestinationBuffer);
  86.    Converts hexnumber h (with length l bytes) to base64 string d.
  87.    Returns length of base64 string.
  88. */
  89. int htob64(char *h, char *d, unsigned int l){
  90.     unsigned int i,j,k;
  91.     unsigned char m,t;
  92.  
  93.     if (!l) return 0;
  94.     l<<=3;                              // no. bits
  95.     m=0x80;
  96.     for (i=0,j=0,k=0,t=0; i<l; i++){
  97.         if (h[(i>>3)]&m) t|=1;
  98.         j++;
  99.         if (!(m>>=1)) m=0x80;
  100.         if (!(j%6)) {
  101.             d[k]=B64ABC[t];
  102.             t&=0;
  103.             k++;
  104.         }
  105.         t<<=1;
  106.     }
  107.     m=5-(j%6);
  108.     t<<=m;
  109.     if (m) {
  110.         d[k]=B64ABC[t];
  111.         k++;
  112.     }
  113.     d[k]&=0;
  114.     return strlen(d);
  115. }
  116.  
  117. unsigned char B64[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  118.  
  119. const char *prime1080="FBE1022E23D213E8ACFA9AE8B9DFADA3EA6B7AC7A7B7E95AB5EB2DF858921FEADE95E6AC7BE7DE6ADBAB8A783E7AF7A7FA6A2B7BEB1E72EAE2B72F9FA2BFB2A2EFBEFAC868BADB3E828FA8BADFADA3E4CC1BE7E8AFE85E9698A783EB68FA07A77AB6AD7BEB618ACF9CA2897EB28A6189EFA07AB99A8A7FA9AE299EFA7BA66DEAFEFBEFBF0B7D8B";
  120.  
  121. int base64dec(char c)
  122. {
  123.     int i;
  124.  
  125.     for (i = 0; i < 64; i++)
  126.         if (B64[i] == c) return i;
  127.  
  128.     return 0;
  129. }
  130.  
  131. char *encrypts(char *key,char *str) {
  132.   char *result;
  133.   unsigned int length;
  134.   unsigned int left,right;
  135.   char *s,*d;
  136.   unsigned char *p;
  137.   BF_KEY bfkey;
  138.   int i;
  139.  
  140.   if(key==NULL||str==NULL) return NULL;
  141.  
  142.   length=strlen(str);
  143.   BF_set_key(&bfkey, strlen(key), (const unsigned char *)key);
  144.  
  145.   s=(char *)malloc(length+9);
  146.  
  147.   strncpy(s,str,length);
  148.   memset(s+length,0,9);
  149.  
  150.   result=(char *)malloc(((length%8==0) ? length/8*12 : 12+length/8*12)+1);
  151.  
  152.   p=(unsigned char *)s;
  153.   d=result;
  154.  
  155.   while(*p) {
  156.     BF_ecb_encrypt((const unsigned char *)p, (unsigned char *)p, &bfkey, BF_ENCRYPT);
  157.     left = ((*p++) << 24);
  158.     left += ((*p++) << 16);
  159.     left += ((*p++) << 8);
  160.     left += (*p++);
  161.     right = ((*p++) << 24);
  162.     right += ((*p++) << 16);
  163.     right += ((*p++) << 8);
  164.     right += (*p++);
  165.     for (i = 0; i < 6; i++) {
  166.         *d++=B64[right & 0x3f];
  167.         right = (right >> 6);
  168.     }
  169.  
  170.     for (i = 0; i < 6; i++) {
  171.         *d++=B64[left & 0x3f];
  172.         left = (left >> 6);
  173.     }
  174.   }
  175.   *d = '\0';
  176.  
  177.   memset(s,0,length+9);
  178.   free(s);
  179.   return result;
  180. }
  181.  
  182. char *decrypts(char *key, char *str) {
  183.   char *result;
  184.   unsigned int length;
  185.   unsigned int left,right;
  186.   int i;
  187.   char *d;
  188.   unsigned char *c;
  189.   BF_KEY bfkey;
  190.  
  191.   if(key==NULL||str==NULL) return NULL;
  192.  
  193.   length=strlen(str);
  194.   BF_set_key(&bfkey,strlen(key),(const unsigned char *)key);
  195.  
  196.   result=(char *)malloc((length/12*8)+1);
  197.   c=(unsigned char *)result;
  198.   d=str;
  199.   while(*d) {
  200.     right=0;
  201.     left=0;
  202.     for (i = 0; i < 6; i++) right |= (base64dec(*d++)) << (i * 6);
  203.     for (i = 0; i < 6; i++) left |= (base64dec(*d++)) << (i * 6);
  204.     right=htonl(right);
  205.     left=htonl(left);
  206.     memcpy(c,&left,4);
  207.     memcpy(c+4,&right,4);
  208.     BF_ecb_encrypt(c,c,&bfkey,BF_DECRYPT);
  209.     c+=8;
  210.   }
  211.   *c='\0';
  212.   return result;
  213. }
  214.  
  215. class CKeyExchangeTimer : public CTimer {
  216. public:
  217.     CKeyExchangeTimer(CModule* pModule)
  218.             : CTimer(pModule, 5, 0, "KeyExchangeTimer", "Key exchange timer removes stale exchanges") {}
  219.  
  220. protected:
  221.     virtual void RunJob();
  222. };
  223.  
  224. class CFishMod : public CModule {
  225. public:
  226.     MODCONSTRUCTOR(CFishMod) {}
  227.     virtual ~CFishMod() {
  228.     }
  229.  
  230.     virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
  231.         // if we have an 'old version', simply upgrade it
  232.         MCString::iterator version = FindNV("version");
  233.  
  234.         // oldest version, before any version numbers!
  235.         // this upgrades to version 1, which changes our key database
  236.         // this does /not/ delete the old keys however, so people can go right back to the old version
  237.         if (version == EndNV()) {
  238.             if (BeginNV() != EndNV()) {  // if we actually have any keys to convert
  239.                 // need to do this since we're adding to NV, and if we don't it loops forever, processing new entries
  240.                 MCString::iterator it = BeginNV();
  241.                 while (it != EndNV()) {
  242.                     it++;
  243.                 }
  244.                 it--;
  245.  
  246.                 CString LastNV = it->first;
  247.  
  248.                 // now loop over every key and upgrade
  249.                 for (it = BeginNV(); it->first != LastNV; it++) {
  250.                     SetNV("key " + it->first, it->second);
  251.                     PutModule("key for " + it->first + " upgraded");
  252.                 }
  253.                 SetNV("key " + it->first, it->second);
  254.                 PutModule("key for " + it->first + " upgraded");
  255.  
  256.                 PutModule("Upgraded Database to Version 1");
  257.             }
  258.  
  259.             SetNV("config prefix_encrypted", "\00312e\003  ");
  260.             SetNV("config prefix_decrypted", "\00304d\003  ");
  261.  
  262.             SetNV("version", "1");
  263.         }
  264.  
  265.         return true;
  266.     }
  267.  
  268.     virtual EModRet OnPrivNotice(CNick& Nick, CString& sMessage) {
  269.         CString command = sMessage.Token(0);
  270.         CString sOtherPub_Key = sMessage.Token(1);
  271.  
  272.         if (command.CaseCmp("DH1080_INIT") == 0 && !sOtherPub_Key.empty()) {
  273.             CString sPriv_Key;
  274.             CString sPub_Key;
  275.             CString sSecretKey;
  276.  
  277.             DH1080_gen(sPriv_Key, sPub_Key);
  278.             if (!DH1080_comp(sPriv_Key, sOtherPub_Key, sSecretKey)) {
  279.                 PutModule("Error in DH1080 with " + Nick.GetNick() + ": " + sSecretKey);
  280.                 return CONTINUE;
  281.             }
  282.             PutModule("Received DH1080 public key from " + Nick.GetNick() + ", sending mine...");
  283.             PutIRC("NOTICE " + Nick.GetNick() + " :DH1080_FINISH " + sPub_Key);
  284.             SetNV("key " + Nick.GetNick().AsLower(), sSecretKey);
  285.             PutModule("Key for " + Nick.GetNick() + " successfully set.");
  286.             return HALT;
  287.         } else if (command.CaseCmp("DH1080_FINISH") == 0 && !sOtherPub_Key.empty()) {
  288.             CString sPriv_Key;
  289.             CString sSecretKey;
  290.  
  291.             map<CString, pair<time_t, CString> >::iterator it = m_msKeyExchange.find(Nick.GetNick().AsLower());
  292.             if (it == m_msKeyExchange.end()) {
  293.                 PutModule("Received unexpected DH1080_FINISH from " + Nick.GetNick() + ".");
  294.             } else {
  295.                 sPriv_Key = it->second.second;
  296.                 if (DH1080_comp(sPriv_Key, sOtherPub_Key, sSecretKey)) {
  297.                     SetNV("key " + Nick.GetNick().AsLower(), sSecretKey);
  298.                     PutModule("Key for " + Nick.GetNick() + " successfully set.");
  299.                     m_msKeyExchange.erase(Nick.GetNick().AsLower());
  300.                 }
  301.             }
  302.             return HALT;
  303.         } else {
  304.             FilterIncoming(Nick.GetNick(), Nick, sMessage);
  305.         }
  306.  
  307.         return CONTINUE;
  308.     }
  309.  
  310.     virtual EModRet OnUserMsg(CString& sTarget, CString& sMessage) {
  311.         MCString::iterator it = FindNV("key " + sTarget.AsLower());
  312.  
  313.         if (sMessage.Left(2) == "-e") {
  314.             sMessage.LeftChomp(3);
  315.             return CONTINUE;
  316.         }
  317.  
  318.         if (it != EndNV()) {
  319.             CChan* pChan = m_pNetwork->FindChan(sTarget);
  320.             if ((pChan) && !(pChan->AutoClearChanBuffer())) {
  321.                 pChan->AddBuffer(":" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage);
  322.             }
  323.             char * cMsg = encrypts((char *)it->second.c_str(), (char *)sMessage.c_str());
  324.  
  325.             CString sMsg = "+OK " + CString(cMsg);
  326.             PutIRC("PRIVMSG " + sTarget + " :" + sMsg);
  327.             m_pUser->PutUser(":" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage, NULL, m_pClient);
  328.  
  329.             free(cMsg);
  330.  
  331.             // relay to other clients
  332.             const vector<CClient*>& vClients = this->m_pNetwork->GetClients();
  333.             for (unsigned int a = 0; a < vClients.size(); a++) {
  334.                 CClient* pClient = vClients[a];
  335.  
  336.                 if (pClient != this->GetClient()) {
  337.                     pClient->PutClient(":" + this->GetClient()->GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage);
  338.                 }
  339.             }
  340.  
  341.             // stop ZNC from handling message, or else it gets sent unencrypted to target as well
  342.             return HALTCORE;
  343.         }
  344.  
  345.         return CONTINUE;
  346.     }
  347.  
  348.     virtual EModRet OnUserAction(CString& sTarget, CString& sMessage) {
  349.         MCString::iterator it = FindNV("key " + sTarget.AsLower());
  350.  
  351.         if (it != EndNV()) {
  352.             CChan* pChan = m_pNetwork->FindChan(sTarget);
  353.             if ((pChan) && !(pChan->AutoClearChanBuffer())) {
  354.                 pChan->AddBuffer(":" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :\001ACTION " + sMessage + "\001");
  355.             }
  356.             char * cMsg = encrypts((char *)it->second.c_str(), (char *)sMessage.c_str());
  357.  
  358.             CString sMsg = "+OK " + CString(cMsg);
  359.             PutIRC("PRIVMSG " + sTarget + " :\001ACTION " + sMsg + "\001");
  360.             m_pUser->PutUser(":" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :\001ACTION " + sMessage + "\001", NULL, m_pClient);
  361.  
  362.             free(cMsg);
  363.  
  364.             // relay to other clients
  365.             const vector<CClient*>& vClients = this->m_pNetwork->GetClients();
  366.             for (unsigned int a = 0; a < vClients.size(); a++) {
  367.                 CClient* pClient = vClients[a];
  368.  
  369.                 if (pClient != this->GetClient()) {
  370.                     pClient->PutClient(":" + this->GetClient()->GetNickMask() + " PRIVMSG " + sTarget + " :\001ACTION " + sMessage + "\001");
  371.                 }
  372.             }
  373.  
  374.             // stop ZNC from handling message, or else it gets sent unencrypted to target as well
  375.             return HALTCORE;
  376.         }
  377.  
  378.         return CONTINUE;
  379.     }
  380.  
  381.     virtual EModRet OnUserNotice(CString& sTarget, CString& sMessage) {
  382.         MCString::iterator it = FindNV("key " + sTarget.AsLower());
  383.  
  384.         if (it != EndNV()) {
  385.             CChan* pChan = m_pNetwork->FindChan(sTarget);
  386.             if ((pChan) && !(pChan->AutoClearChanBuffer())) {
  387.                 pChan->AddBuffer(":" + m_pNetwork->GetIRCNick().GetNickMask() + " NOTICE " + sTarget + " :" + sMessage);
  388.             }
  389.             char * cMsg = encrypts((char *)it->second.c_str(), (char *)sMessage.c_str());
  390.  
  391.             CString sMsg = "+OK " + CString(cMsg);
  392.             PutIRC("NOTICE " + sTarget + " :" + sMsg);
  393.             m_pUser->PutUser(":" + m_pNetwork->GetIRCNick().GetNickMask() + " NOTICE " + sTarget + " :" + sMessage, NULL, m_pClient);
  394.  
  395.             free(cMsg);
  396.  
  397.             // relay to other clients
  398.             const vector<CClient*>& vClients = this->m_pNetwork->GetClients();
  399.             for (unsigned int a = 0; a < vClients.size(); a++) {
  400.                 CClient* pClient = vClients[a];
  401.  
  402.                 if (pClient != this->GetClient()) {
  403.                     pClient->PutClient(":" + this->GetClient()->GetNickMask() + " NOTICE " + sTarget + " :" + sMessage);
  404.                 }
  405.             }
  406.  
  407.             // stop ZNC from handling message, or else it gets sent unencrypted to target as well
  408.             return HALTCORE;
  409.         }
  410.  
  411.         return CONTINUE;
  412.  
  413.     }
  414.  
  415.     virtual EModRet OnUserTopic(CString& sChannel, CString& sTopic) {
  416.         if (!sTopic.empty()) {
  417.             MCString::iterator it = FindNV("key " + sChannel.AsLower());
  418.             if (it != EndNV()) {
  419.                 char * cTopic = encrypts((char *)it->second.c_str(), (char *)sTopic.c_str());
  420.                 sTopic = "+OK " + CString(cTopic);
  421.                 free(cTopic);
  422.             }
  423.         }
  424.  
  425.         return CONTINUE;
  426.     }
  427.  
  428.     virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {
  429.         FilterIncoming(Nick.GetNick(), Nick, sMessage);
  430.         return CONTINUE;
  431.     }
  432.  
  433.     virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) {
  434.         FilterIncoming(Channel.GetName(), Nick, sMessage);
  435.         return CONTINUE;
  436.     }
  437.  
  438.     virtual EModRet OnPrivAction(CNick& Nick, CString& sMessage) {
  439.         FilterIncoming(Nick.GetNick(), Nick, sMessage);
  440.         return CONTINUE;
  441.     }
  442.  
  443.     virtual EModRet OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage) {
  444.         FilterIncoming(Channel.GetName(), Nick, sMessage);
  445.         return CONTINUE;
  446.     }
  447.    
  448.     virtual EModRet OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) {
  449.         FilterIncoming(Channel.GetName(), Nick, sTopic);
  450.         return CONTINUE;
  451.     }
  452.  
  453.     virtual EModRet OnRaw(CString& sLine) {
  454.         if (sLine.WildCmp(":* 332 *") && sLine.Token(1) == "332") {
  455.             CChan* pChan = m_pNetwork->FindChan(sLine.Token(3));
  456.             if (pChan) {
  457.                 CNick Nick(sLine.Token(2));
  458.                 CString sTopic = sLine.Token(4, true);
  459.                 sTopic.LeftChomp();
  460.                 FilterIncoming(pChan->GetName(), Nick, sTopic);
  461.                 sLine = sLine.Token(0) + " " + sLine.Token(1) + " " + sLine.Token(2) + " " + pChan->GetName() + " :" + sTopic;
  462.             }
  463.         }
  464.         return CONTINUE;
  465.     }
  466.  
  467.     void FilterIncoming(const CString& sTarget, CNick& Nick, CString& sMessage) {
  468.         MCString::iterator it = FindNV("key " + sTarget.AsLower());
  469.  
  470.         if (it != EndNV()) {
  471.             if (sMessage.Left(4) == "+OK " || sMessage.Left(5) == "mcps ") {
  472.                 if (sMessage.Left(4) == "+OK ") {
  473.                     sMessage.LeftChomp(4);
  474.                 } else if (sMessage.Left(5) == "mcps ") {
  475.                     sMessage.LeftChomp(5);
  476.                 }
  477.  
  478.                 unsigned int msg_len = strlen(sMessage.c_str());
  479.  
  480.                 if ((strspn(sMessage.c_str(), (char *)B64) != msg_len) || msg_len < 12) {
  481.                     return;
  482.                 }
  483.  
  484.                 unsigned int mark_broken_block = 0;
  485.  
  486.                 if (msg_len != (msg_len/12)*12) {
  487.                     msg_len = msg_len - (msg_len/12)*12;
  488.                     sMessage.RightChomp(msg_len);
  489.                     mark_broken_block = 1;
  490.                 }
  491.  
  492.                 char *cMsg = decrypts((char *)it->second.c_str(), (char *)sMessage.c_str());
  493.                 sMessage = GetNV("config prefix_encrypted") + CString(cMsg);  // blue  'e'  for nice, encrypted
  494.  
  495.                 if (mark_broken_block) {
  496.                     sMessage += "  \002&\002";
  497.                 }
  498.  
  499.                 free(cMsg);
  500.             } else {
  501.                 sMessage = GetNV("config prefix_decrypted") + sMessage;  // red  'd'  for bad, not encrypted
  502.             }
  503.         }
  504.     }
  505.  
  506.     virtual void OnModCommand(const CString& sCommand) {
  507.         CString sCmd = sCommand.Token(0);
  508.  
  509.         if (sCmd.CaseCmp("DELKEY") == 0) {
  510.             CString sTarget = sCommand.Token(1);
  511.  
  512.             if (!sTarget.empty()) {
  513.                 if (DelNV("key " + sTarget.AsLower())) {
  514.                     PutModule("Target [" + sTarget + "] deleted");
  515.                 } else {
  516.                     PutModule("Target [" + sTarget + "] not found");
  517.                 }
  518.             } else {
  519.                 PutModule("Usage DelKey <#chan|Nick>");
  520.             }
  521.         } else if (sCmd.CaseCmp("SETKEY") == 0) {
  522.             CString sTarget = sCommand.Token(1);
  523.             CString sKey = sCommand.Token(2, true);
  524.  
  525.             if (!sKey.empty()) {
  526.                 SetNV("key " + sTarget.AsLower(), sKey);
  527.                 PutModule("Set encryption key for [" + sTarget + "] to [" + sKey + "]");
  528.             } else {
  529.                 PutModule("Usage: SetKey <#chan|Nick> <Key>");
  530.             }
  531.         } else if (sCmd.CaseCmp("SHOWKEY") == 0) {
  532.             CString sTarget = sCommand.Token(1);
  533.  
  534.             if (!sTarget.empty()) {
  535.                 MCString::iterator it = FindNV("key " + sTarget.AsLower());
  536.  
  537.                 if (it != EndNV()) {
  538.                     PutModule("Target key is " + it->second);
  539.                 } else {
  540.                     PutModule("Target not found.");
  541.                 }
  542.             } else {
  543.                 PutModule("Usage ShowKey <#chan|Nick>");
  544.             }
  545.         } else if (sCmd.CaseCmp("LISTKEYS") == 0) {
  546.             if (BeginNV() == EndNV()) {
  547.                 PutModule("You have no encryption keys set.");
  548.             } else {
  549.                 CTable Table;
  550.                 Table.AddColumn("Target");
  551.                 Table.AddColumn("Key");
  552.  
  553.                 // find all our keys and print them out
  554.                 for (MCString::iterator it = BeginNV(); it != EndNV(); it++) {
  555.                     if (it->first.Left(4) == "key ") {
  556.                         Table.AddRow();
  557.                         Table.SetCell("Target", it->first.LeftChomp_n(4));  // remove "key " from start
  558.                         Table.SetCell("Key", it->second);
  559.                     }
  560.                 }
  561.  
  562.                 if (Table.size()) {
  563.                         unsigned int uTableIdx = 0;
  564.                         CString sLine;
  565.  
  566.                         while (Table.GetLine(uTableIdx++, sLine)) {
  567.                                 PutModule(sLine);
  568.                         }
  569.                 }
  570.             }
  571.         } else if (sCmd.CaseCmp("LISTCONFIG") == 0) {
  572.             // we would use tables here, but they mangle things like irc colour codes >.>
  573.             for (MCString::iterator it = BeginNV(); it != EndNV(); it++) {
  574.                 if (it->first.Left(7) == "config ") {
  575.                     PutModule(it->first.LeftChomp_n(7) + " : \"" + it->second + "\"");
  576.                 }
  577.             }
  578.         } else if (sCmd.CaseCmp("SETCONFIG") == 0) {
  579.             CString sName = sCommand.Token(1);
  580.             CString sValue = sCommand.Token(2, true);
  581.  
  582.             if (!sValue.empty()) {
  583.                 SetNV("config " + sName.AsLower(), sValue);
  584.                 PutModule("Set config option [" + sName + "] to [" + sValue + "]");
  585.             } else {
  586.                 PutModule("Usage: SetConfig <Name> <Value>");
  587.             }
  588.         } else if (sCmd.CaseCmp("KEYX") == 0) {
  589.             CString sTarget = sCommand.Token(1);
  590.  
  591.             if (sTarget.empty()) {
  592.                 PutModule("You did not specify a target for the key exchange.");
  593.             } else {
  594.                 map<CString, pair<time_t, CString> >::iterator it = m_msKeyExchange.find(sTarget.AsLower());
  595.                 if (it != m_msKeyExchange.end()) {
  596.                     PutModule("Keyexchange with " + sTarget + " already in progress.");
  597.                 } else {
  598.                     CString sPriv_Key;
  599.                     CString sPub_Key;
  600.  
  601.                     DH1080_gen(sPriv_Key, sPub_Key);
  602.                     m_msKeyExchange.insert(make_pair(sTarget.AsLower(), make_pair(time(NULL), sPriv_Key)));
  603.                     PutIRC("NOTICE " + sTarget + " :DH1080_INIT " + sPub_Key);
  604.                     PutModule("Sent my DH1080 public key to " + sTarget + ", waiting for reply ...");
  605.                     if (FindTimer("KeyExchangeTimer") == NULL) {
  606.                         AddTimer(new CKeyExchangeTimer(this));
  607.                     }
  608.                 }
  609.             }
  610.         } else if (sCmd.CaseCmp("HELP") == 0) {
  611.             CTable Table;
  612.             Table.AddColumn("Command");
  613.             Table.AddColumn("Arguments");
  614.             Table.AddColumn("Description");
  615.  
  616.             // list all our commands
  617.             Table.AddRow();
  618.             Table.SetCell("Command", "SetKey");
  619.             Table.SetCell("Arguments", "<target> <key>");
  620.             Table.SetCell("Description", "Sets <target>'s FiSH encryption key");
  621.  
  622.             Table.AddRow();
  623.             Table.SetCell("Command", "DelKey");
  624.             Table.SetCell("Arguments", "<target>");
  625.             Table.SetCell("Description", "Removes <target>'s FiSH encryption key");
  626.  
  627.             Table.AddRow();
  628.             Table.SetCell("Command", "ShowKey");
  629.             Table.SetCell("Arguments", "<target>");
  630.             Table.SetCell("Description", "Show the encryption key of <target>, if it has one set");
  631.  
  632.             Table.AddRow();
  633.             Table.SetCell("Command", "ListKeys");
  634.             Table.SetCell("Arguments", "");
  635.             Table.SetCell("Description", "Print out all of our keys");
  636.  
  637.             Table.AddRow();
  638.             Table.SetCell("Command", "SetConfig");
  639.             Table.SetCell("Arguments", "<name> <value>");
  640.             Table.SetCell("Description", "Set config option <name> to <value>");
  641.  
  642.             Table.AddRow();
  643.             Table.SetCell("Command", "ListConfig");
  644.             Table.SetCell("Arguments", "");
  645.             Table.SetCell("Description", "Print out all of our config options");
  646.  
  647.             Table.AddRow();
  648.             Table.SetCell("Command", "KeyX");
  649.             Table.SetCell("Arguments", "<target>");
  650.             Table.SetCell("Description", "Start a key exchange with <target>");
  651.  
  652.             Table.AddRow();
  653.             Table.SetCell("Command", "Help");
  654.             Table.SetCell("Arguments", "");
  655.             Table.SetCell("Description", "Display this message");
  656.  
  657.             PutModule(Table);
  658.         } else {
  659.             PutModule("Unknown command, try 'Help'");
  660.         }
  661.     }
  662.  
  663.     void DelStaleKeyExchanges(time_t iTime) {
  664.         for (map<CString, pair<time_t, CString> >::const_iterator it = m_msKeyExchange.begin(); it != m_msKeyExchange.end(); it++) {
  665.             if (iTime - 5 >= it->second.first) {
  666.             PutModule("Keyexchange with " + it->first + " expired before completion.");
  667.                 m_msKeyExchange.erase(it->first);
  668.             }
  669.         }
  670.         if (m_msKeyExchange.size() <= 0) {
  671.             RemTimer("KeyExchangeTimer");
  672.         }
  673.     }
  674.  
  675. private:
  676.  
  677.     void DH1080_gen(CString& sPriv_Key, CString& sPub_Key) {
  678.         sPriv_Key = "";
  679.         sPub_Key = "";
  680.  
  681.         unsigned char raw_buf[200];
  682.         unsigned long len;
  683.         unsigned char *a, *b;
  684.  
  685.         DH *dh;
  686.         BIGNUM *b_prime=NULL;
  687.         BIGNUM *b_generator=NULL;
  688.  
  689.         initb64();
  690.  
  691.         dh=DH_new();
  692.  
  693.         if (!BN_hex2bn(&b_prime, prime1080)) {
  694.             return;
  695.         }
  696.  
  697.         if (!BN_dec2bn(&b_generator, "2")) {
  698.             return;
  699.         }
  700.  
  701.         dh->p=b_prime;
  702.         dh->g=b_generator;
  703.  
  704.         if (!DH_generate_key(dh)) {
  705.             return;
  706.         }
  707.  
  708.         len = BN_num_bytes(dh->priv_key);
  709.         a = (unsigned char *)malloc(len);
  710.         BN_bn2bin(dh->priv_key,a);
  711.  
  712.         memset(raw_buf, 0, 200);
  713.         htob64((char *)a, (char *)raw_buf, len);
  714.         sPriv_Key = CString((char *)raw_buf);
  715.         len=BN_num_bytes(dh->pub_key);
  716.         b = (unsigned char *)malloc(len);
  717.         BN_bn2bin(dh->pub_key,b);
  718.         memset(raw_buf, 0, 200);
  719.         htob64((char *)b, (char *)raw_buf, len);
  720.         sPub_Key = CString((char *)raw_buf);
  721.         DH_free(dh);
  722.         free(a);
  723.         free(b);
  724.     }
  725.  
  726.  
  727.     bool DH1080_comp(CString& sPriv_Key, CString& sOtherPub_Key, CString& sSecret_Key) {
  728.         int len;
  729.         unsigned char SHA256digest[32];
  730.         char *key;
  731.         BIGNUM *b_prime=NULL;
  732.         BIGNUM *b_myPrivkey=NULL;
  733.         BIGNUM *b_HisPubkey=NULL;
  734.         BIGNUM *b_generator=NULL;
  735.         DH *dh;
  736.         CString sSHA256digest;
  737.         unsigned char raw_buf[200];
  738.  
  739.         if (!BN_hex2bn(&b_prime, prime1080)) {
  740.             return false;
  741.         }
  742.  
  743.         if (!BN_dec2bn(&b_generator, "2")) {
  744.             return false;
  745.         }
  746.  
  747.         dh=DH_new();
  748.         dh->p=b_prime;
  749.         dh->g=b_generator;
  750.  
  751.         memset(raw_buf, 0, 200);
  752.         len = b64toh((char *)sPriv_Key.c_str(), (char *)raw_buf);
  753.         b_myPrivkey=BN_bin2bn(raw_buf, len, NULL);
  754.         dh->priv_key=b_myPrivkey;
  755.  
  756.         memset(raw_buf, 0, 200);
  757.         len = b64toh((char *)sOtherPub_Key.c_str(), (char *)raw_buf);
  758.  
  759.         b_HisPubkey=BN_bin2bn(raw_buf, len, NULL);
  760.  
  761.         key=(char *)malloc(DH_size(dh));
  762.         memset(key, 0, DH_size(dh));
  763.         len=DH_compute_key((unsigned char *)key, b_HisPubkey, dh);
  764.         if (len == -1) {
  765.             // Bad pub key
  766.             unsigned long err = ERR_get_error();
  767.             DEBUG("** DH Error:" << ERR_error_string(err,NULL));
  768.             DH_free(dh);
  769.             BN_clear_free(b_HisPubkey);
  770.             free(key);
  771.  
  772.             sSecret_Key = CString(ERR_error_string(err,NULL)).Token(4,true,":");
  773.             return false;
  774.         }
  775.  
  776.         SHA256_CTX c;
  777.         SHA256_Init(&c);
  778.         memset(SHA256digest, 0, 32);
  779.         SHA256_Update(&c, key, len);
  780.         SHA256_Final(SHA256digest, &c);
  781.         memset(raw_buf, 0, 200);
  782.         len = htob64((char *)SHA256digest, (char *)raw_buf, 32);
  783.         sSecret_Key = "";
  784.         sSecret_Key.append((char *)raw_buf, len);
  785.  
  786.         DH_free(dh);
  787.         BN_clear_free(b_HisPubkey);
  788.         free(key);
  789.         return true;
  790.     }
  791.  
  792.     map<CString, pair<time_t, CString> >    m_msKeyExchange;
  793.  
  794. };
  795.  
  796. void CKeyExchangeTimer::RunJob() {
  797.         CFishMod *p = (CFishMod *)m_pModule;
  798.         p->DelStaleKeyExchanges(time(NULL));
  799. }
  800.  
  801. template<> void TModInfo<CFishMod>(CModInfo& Info) {
  802.         Info.SetWikiPage("CFishMod");
  803. }
  804.  
  805. NETWORKMODULEDEFS(CFishMod, "FiSH encryption for channel/private messages")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement