Changeset 1911

Show
Ignore:
Timestamp:
06/05/00 03:00:39 (9 years ago)
Author:
graham
Message:

Priliminary support for OpenSSL secure socket encryption using
d/h key exchange and des xcbc encryption.

Location:
trunk/licq/src
Files:
2 added
15 modified

Legend:

Unmodified
Added
Removed
  • trunk/licq/src/daemon/icqd-tcp.cpp

    r1848 r1911  
    77#include <sys/types.h> 
    88#include <unistd.h> 
    9 #include <iostream.h> 
     9//#include <iostream.h> 
    1010#include <errno.h> 
    1111 
     
    2323#include "support.h" 
    2424 
     25#include "licq_openssl.h" 
     26#ifdef USE_OPENSSL 
     27#include <openssl/bn.h> 
     28#include <openssl/des.h> 
     29#include <openssl/crypto.h> 
     30#endif 
     31 
    2532 
    2633//-----ICQ::sendMessage---------------------------------------------------------------------------- 
     
    5461     CPU_ThroughServer *p = new CPU_ThroughServer(_nUin, 
    5562        ICQ_CMDxSUB_MSG | (bMultipleRecipients ? ICQ_CMDxSUB_FxMULTIREC : 0), mDos); 
    56      gLog.Info("%sSending message through server (#%ld).\n", L_UDPxSTR, p->getSequence()); 
     63     gLog.Info("%sSending message through server (#%ld).\n", L_UDPxSTR, p->Sequence()); 
    5764     result = SendExpectEvent_Server(_nUin, p, e); 
    5865  } 
     
    6067  { 
    6168    if (u == NULL) return NULL; 
     69#ifdef USE_OPENSSL 
     70    if (u->Secure()) f |= E_ENCRYPTED; 
     71#endif 
    6272    e = new CEventMsg(m, ICQ_CMDxTCP_START, TIME_NOW, f); 
    6373    CPT_Message *p = new CPT_Message(mDos, nLevel, bMultipleRecipients, u); 
    6474    gLog.Info("%sSending %smessage to %s (#%ld).\n", L_TCPxSTR, 
    6575       nLevel == ICQ_TCPxMSG_URGENT ? "urgent " : "", 
    66        u->GetAlias(), -p->getSequence()); 
     76       u->GetAlias(), -p->Sequence()); 
    6777    result = SendExpectEvent_Client(u, p, e); 
    6878  } 
     
    8999  CPT_ReadAwayMessage *p = new CPT_ReadAwayMessage(u); 
    90100  gLog.Info("%sRequesting auto response from %s (#%ld).\n", L_TCPxSTR, 
    91             u->GetAlias(), -p->getSequence()); 
     101            u->GetAlias(), -p->Sequence()); 
    92102  ICQEvent *result = SendExpectEvent_Client(u, p, NULL); 
    93103  gUserManager.DropUser(u); 
     
    129139    CPU_ThroughServer *p = new CPU_ThroughServer(_nUin, 
    130140       ICQ_CMDxSUB_URL | (bMultipleRecipients ? ICQ_CMDxSUB_FxMULTIREC : 0), m); 
    131     gLog.Info("%sSending url through server (#%ld).\n", L_UDPxSTR, p->getSequence()); 
     141    gLog.Info("%sSending url through server (#%ld).\n", L_UDPxSTR, p->Sequence()); 
    132142    result = SendExpectEvent_Server(_nUin, p, e); 
    133143  } 
     
    139149    gLog.Info("%sSending %sURL to %s (#%ld).\n", L_TCPxSTR, 
    140150       nLevel == ICQ_TCPxMSG_URGENT ? "urgent " : "", 
    141        u->GetAlias(), -p->getSequence()); 
     151       u->GetAlias(), -p->Sequence()); 
    142152    result = SendExpectEvent_Client(u, p, e); 
    143153  } 
     
    184194    if (nLevel == ICQ_TCPxMSG_URGENT) f |= E_URGENT; 
    185195    e = new CEventFile(szFilename, p->GetDescription(), p->GetFileSize(), 
    186                        p->getSequence(), TIME_NOW, f); 
     196                       p->Sequence(), TIME_NOW, f); 
    187197    gLog.Info("%sSending %sfile transfer to %s (#%ld).\n", L_TCPxSTR, 
    188198       nLevel == ICQ_TCPxMSG_URGENT ? "urgent " : "", 
    189        u->GetAlias(), -p->getSequence()); 
     199       u->GetAlias(), -p->Sequence()); 
    190200    result = SendExpectEvent_Client(u, p, e); 
    191201  } 
     
    242252    CPU_ThroughServer *p = new CPU_ThroughServer(nUin, 
    243253       ICQ_CMDxSUB_CONTACTxLIST | (bMultipleRecipients ? ICQ_CMDxSUB_FxMULTIREC : 0), m); 
    244     gLog.Info("%sSending contact list through server (#%ld).\n", L_UDPxSTR, p->getSequence()); 
     254    gLog.Info("%sSending contact list through server (#%ld).\n", L_UDPxSTR, p->Sequence()); 
    245255    result = SendExpectEvent_Server(nUin, p, e); 
    246256  } 
     
    252262    gLog.Info("%sSending %scontact list to %s (#%ld).\n", L_TCPxSTR, 
    253263       nLevel == ICQ_TCPxMSG_URGENT ? "urgent " : "", 
    254        u->GetAlias(), -p->getSequence()); 
     264       u->GetAlias(), -p->Sequence()); 
    255265    result = SendExpectEvent_Client(u, p, e); 
    256266  } 
     
    340350  unsigned long f = E_DIRECT | INT_VERSION; 
    341351  if (nLevel == ICQ_TCPxMSG_URGENT) f |= E_URGENT; 
    342   CEventChat *e = new CEventChat(reason, szChatUsers, nPort, p->getSequence(), 
     352  CEventChat *e = new CEventChat(reason, szChatUsers, nPort, p->Sequence(), 
    343353     TIME_NOW, f); 
    344354  gLog.Info("%sSending %schat request to %s (#%ld).\n", L_TCPxSTR, 
    345355     nLevel == ICQ_TCPxMSG_URGENT ? "urgent " : "", 
    346      u->GetAlias(), -p->getSequence()); 
     356     u->GetAlias(), -p->Sequence()); 
    347357  ICQEvent *result = SendExpectEvent_Client(u, p, e); 
    348358  u->SetSendServer(false); 
     
    405415} 
    406416 
     417/*--------------------------------------------------------------------------- 
     418 * OpenSSL stuff 
     419 *-------------------------------------------------------------------------*/ 
     420 
     421CICQEventTag *CICQDaemon::icqSendKeyRequest(unsigned long nUin) 
     422{ 
     423#ifdef USE_OPENSSL 
     424  ICQEvent *result = NULL; 
     425 
     426  ICQUser *u = gUserManager.FetchUser(nUin, LOCK_W); 
     427  if (u == NULL) 
     428  { 
     429    gLog.Warn("%sCannot send key request to user not on list (%ld).\n", 
     430       L_WARNxSTR, nUin); 
     431    return NULL; 
     432  } 
     433 
     434  // Check that the user doesn't already have a secure channel 
     435  if (u->Secure()) 
     436  { 
     437    /*if (u->DHKey()->CryptoStatus() == CRYPTO_HALF) 
     438    { 
     439      gLog.Warn("%sKey request already in progress for %s (%ld).\n", 
     440         L_WARNxSTR, u->GetAlias(), nUin); 
     441      gUserManager.DropUser(u); 
     442      return NULL; 
     443    } 
     444    // Wipe out any old key 
     445    u->ClearDHKey(true);*/ 
     446    gLog.Warn("%s%s (%ld) already has a secure channel.\n", L_WARNxSTR, 
     447       u->GetAlias(), nUin); 
     448    gUserManager.DropUser(u); 
     449    return NULL; 
     450  } 
     451 
     452  // Create a key 
     453  CDHKey *k = new CDHKey; 
     454 
     455  gLog.Info("%sInitiating d/h key exchange with %s (%ld).\n", L_UDPxSTR, 
     456    u->GetAlias(), nUin); 
     457 
     458  BIGNUM *g, *ga, *p, *a; 
     459  char szKey[256] = {0}; 
     460  BN_CTX *temp_ctx = BN_CTX_new(); 
     461 
     462  gLog.Info("%sGenerating encryption key for %s (%ld).\n", L_UDPxSTR, 
     463     u->GetAlias(), nUin); 
     464 
     465  // find a prime p and generator g 
     466  p = BN_new(); 
     467  p = BN_generate_prime(NULL, 192, 1, NULL, NULL, NULL, NULL); 
     468 
     469  // load in our generator, 2 
     470  g = BN_new(); 
     471  BN_dec2bn (&g, "2"); 
     472 
     473  // now we get a random a, and make g^a 
     474  a = BN_new(); 
     475  BN_rand (a, 192, 0, 127); 
     476  ga = BN_new(); 
     477  BN_mod_exp (ga, g, a, p, temp_ctx); 
     478 
     479  BN_copy(k->P(), p); 
     480  BN_copy(k->A(), a); 
     481  BN_copy(k->G(), ga); 
     482  gLog.Info("%sKey for %s (%ld) done.\n", L_UDPxSTR, u->GetAlias(), nUin); 
     483 
     484  // prepare send key 
     485  sprintf (szKey, "%s\n%s\n%s", BN_bn2hex(g), BN_bn2hex(ga), BN_bn2hex(p)); 
     486  k->SetCryptoStatus(CRYPTO_HALF); 
     487 
     488  // clean up 
     489  BN_CTX_free (temp_ctx); 
     490  BN_clear_free (g); 
     491  BN_clear_free (ga); 
     492  BN_clear_free (p); 
     493  BN_clear_free (a); 
     494 
     495  CPT_KeyRequest *pkt = new CPT_KeyRequest(szKey, u, k); 
     496  gLog.Info("%sSending key request to %s (#%ld).\n", L_TCPxSTR, 
     497     u->GetAlias(), -pkt->Sequence()); 
     498  result = SendExpectEvent_Client(u, pkt, NULL); 
     499 
     500  u->SetSendServer(false); 
     501 
     502  CICQEventTag *t = NULL; 
     503  if (result != NULL) 
     504    t = new CICQEventTag(result); 
     505  //else 
     506  //  u->ClearDHKey(true); 
     507 
     508  gUserManager.DropUser(u); 
     509 
     510  return (t); 
     511 
     512#else // No OpenSSL 
     513  gLog.Warn("%sicqSendKeyRequest() to %ld called when we do not support OpenSSL.\n", 
     514     L_WARNxSTR, nUin); 
     515  return NULL; 
     516 
     517#endif 
     518} 
     519 
     520 
     521//-----CICQDaemon::keyCancel------------------------------------------------------------------------- 
     522void CICQDaemon::icqKeyRequestCancel(unsigned long nUin, unsigned long nSequence) 
     523{ 
     524  ICQUser *u = gUserManager.FetchUser(nUin, LOCK_W); 
     525  if (u == NULL) return; 
     526  gLog.Info("%sCancelling key request to %s (#%ld).\n", L_TCPxSTR, 
     527     u->GetAlias(), -nSequence); 
     528  //CPT_CancelKeyRequest p(nSequence, u); 
     529  //AckTCP(p, u->SocketDesc()); 
     530  //u->ClearDHKey(true); 
     531  //u->SetSecure(false); 
     532  // we shouldn't need to do anything here right??? 
     533  gUserManager.DropUser(u); 
     534} 
     535 
     536 
     537 
     538 
     539 
    407540 
    408541/*--------------------------------------------------------------------------- 
     
    552685    return -1; 
    553686  } 
    554  
    555   // Add the new socket to the socket manager 
    556   gSocketManager.AddSocket(s); 
     687  s->SetVersion(nVersion); 
    557688  int nSD = s->Descriptor(); 
    558   s->SetVersion(nVersion); 
    559   gSocketManager.DropSocket(s); 
    560689 
    561690  // Set the socket descriptor in the user 
    562691  u = gUserManager.FetchUser(nUin, LOCK_W); 
    563692  if (u == NULL) return -1; 
    564   u->SetSocketDesc(nSD, nPort, nVersion); 
     693  u->SetSocketDesc(s); 
    565694  u->SetConnectionInProgress(false); 
    566695  gUserManager.DropUser(u); 
     696 
     697  // Add the new socket to the socket manager 
     698  gSocketManager.AddSocket(s); 
     699  gSocketManager.DropSocket(s); 
    567700 
    568701  // Alert the select thread that there is a new socket 
     
    606739  { 
    607740    gLog.Info("%sConnecting to %s at %s:%d.\n", L_TCPxSTR, szAlias, 
    608          ip_ntoa(nIp, buf), nPort); 
     741      ip_ntoa(nIp, buf), nPort); 
    609742    // If we fail to set the remote address, the ip must be 0 
    610743    if (!sock->SetRemoteAddr(nIp, nPort)) return false; 
     
    709842    if (u != NULL) 
    710843    { 
    711       u->SetSocketDesc(nSD, s->LocalPort(), nVersion); 
     844      u->SetSocketDesc(s); 
    712845      gUserManager.DropUser(u); 
    713846    } 
     
    747880bool CICQDaemon::ProcessTcpPacket(TCPSocket *pSock) 
    748881{ 
    749   unsigned long checkUin, theSequence, senderIp, localIp, 
     882  unsigned long nUin, theSequence, senderIp, localIp, 
    750883                senderPort, junkLong, nPort, nPortReversed; 
    751884  unsigned short version, command, junkShort, newCommand, messageLen, 
     
    770903    case 3: 
    771904    { 
    772       packet >> checkUin 
     905      packet >> nUin 
    773906             >> version 
    774907             >> command      // main tcp command (start, cancel, ack) 
    775908             >> junkShort    // 00 00 to fill in the MSB of the command long int which is read in as a short 
    776              >> checkUin 
     909             >> nUin 
    777910             >> newCommand   // sub command (message/chat/read away message/...) 
    778911             >> messageLen   // length of incoming message 
     
    790923        return false; 
    791924      } 
    792       packet >> checkUin 
     925      packet >> nUin 
    793926             >> version 
    794927             >> junkLong     // checksum 
    795928             >> command      // main tcp command (start, cancel, ack) 
    796929             >> junkShort    // 00 00 to fill in the MSB of the command long int which is read in as a short 
    797              >> checkUin 
     930             >> nUin 
    798931             >> newCommand   // sub command (message/chat/read away message/...) 
    799932             >> messageLen   // length of incoming message 
     
    804937    case 7: 
    805938    { 
    806       checkUin = pSock->Owner(); 
     939      nUin = pSock->Owner(); 
    807940      if (!Decrypt_Client(&packet, 6)) 
    808941      { 
     
    832965 
    833966  // Some simple validation of the packet 
    834   if (checkUin == 0 || command == 0 || newCommand == 0) 
     967  if (nUin == 0 || command == 0 || newCommand == 0) 
    835968  { 
    836969    char *buf; 
    837970    gLog.Unknown("%sInvalid TCP packet (uin: %08lx, cmd: %04x, subcmd: %04x):\n%s\n", 
    838                  L_UNKNOWNxSTR, checkUin, command, newCommand, packet.print(buf)); 
     971                 L_UNKNOWNxSTR, nUin, command, newCommand, packet.print(buf)); 
    839972    delete buf; 
    840973    return false; 
    841974  } 
    842975 
    843   if (checkUin == gUserManager.OwnerUin()) 
     976  if (nUin == gUserManager.OwnerUin()) 
    844977  { 
    845978    char *buf; 
     
    8801013  // find which user was sent 
    8811014  bool bNewUser = false; 
    882   ICQUser *u = gUserManager.FetchUser(checkUin, LOCK_W); 
     1015  ICQUser *u = gUserManager.FetchUser(nUin, LOCK_W); 
    8831016  if (u == NULL) 
    8841017  { 
    885     u = new ICQUser(checkUin); 
    886     u->SetSocketDesc(sockfd, pSock->LocalPort(), pSock->Version()); 
     1018    u = new ICQUser(nUin); 
     1019    u->SetSocketDesc(pSock); 
    8871020    bNewUser = true; 
    8881021  } 
     
    8971030  unsigned long nMask = E_DIRECT 
    8981031                        | ((newCommand & ICQ_CMDxSUB_FxMULTIREC) ? E_MULTIxREC : 0) 
    899                         | ((msgFlags & ICQ_TCPxMSG_URGENT) ? E_URGENT : 0); 
     1032                        | ((msgFlags & ICQ_TCPxMSG_URGENT) ? E_URGENT : 0) 
     1033                        | ((pSock->DHKey() != NULL) ? E_ENCRYPTED : 0); 
    9001034  newCommand &= ~ICQ_CMDxSUB_FxMULTIREC; 
    9011035  bool bAccept = msgFlags & ICQ_TCPxMSG_URGENT || msgFlags & ICQ_TCPxMSG_LIST; 
     
    9631097        if (licqChar == 'L') 
    9641098          gLog.Info("%sMessage from %s (%ld) [Licq v0.%d].\n", L_TCPxSTR, u->GetAlias(), 
    965              checkUin, licqVersion); 
     1099             nUin, licqVersion); 
    9661100        else 
    967           gLog.Info("%sMessage from %s (%ld).\n", L_TCPxSTR, u->GetAlias(), checkUin); 
     1101          gLog.Info("%sMessage from %s (%ld).\n", L_TCPxSTR, u->GetAlias(), nUin); 
    9681102 
    9691103        CEventMsg *e = CEventMsg::Parse(message, ICQ_CMDxTCP_START, TIME_NOW, nMask); 
     
    9891123            // FIXME should either refuse the event or have a special auto response 
    9901124            // for rejected events instead of pretending to accept the user 
    991             RejectEvent(checkUin, e); 
     1125            RejectEvent(nUin, e); 
    9921126            break; 
    9931127          } 
     
    10111145        if (licqChar == 'L') 
    10121146          gLog.Info("%s%s (%ld) requested auto response [Licq v0.%d].\n", L_TCPxSTR, 
    1013              u->GetAlias(), checkUin, licqVersion); 
     1147             u->GetAlias(), nUin, licqVersion); 
    10141148        else 
    1015           gLog.Info("%s%s (%ld) requested auto response.\n", L_TCPxSTR, u->GetAlias(), checkUin); 
     1149          gLog.Info("%s%s (%ld) requested auto response.\n", L_TCPxSTR, u->GetAlias(), nUin); 
    10161150        m_sStats[STATS_AutoResponseChecked].Inc(); 
    10171151 
     
    10201154        AckTCP(p, pSock); 
    10211155 
    1022         PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_EVENTS, checkUin)); 
     1156        PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_EVENTS, nUin)); 
    10231157        break; 
    10241158      } 
     
    10321166        if (licqChar == 'L') 
    10331167          gLog.Info("%sURL from %s (%ld) [Licq v0.%d].\n", L_TCPxSTR, u->GetAlias(), 
    1034             checkUin, licqVersion); 
     1168            nUin, licqVersion); 
    10351169        else 
    1036           gLog.Info("%sURL from %s (%ld).\n", L_TCPxSTR, u->GetAlias(), checkUin); 
     1170          gLog.Info("%sURL from %s (%ld).\n", L_TCPxSTR, u->GetAlias(), nUin); 
    10371171 
    10381172        CEventUrl *e = CEventUrl::Parse(message, ICQ_CMDxTCP_START, TIME_NOW, nMask); 
     
    10631197          if (Ignore(IGNORE_NEWUSERS)) 
    10641198          { 
    1065             RejectEvent(checkUin, e); 
     1199            RejectEvent(nUin, e); 
    10661200            break; 
    10671201          } 
     
    10841218        if (licqChar == 'L') 
    10851219          gLog.Info("%sContact list from %s (%ld) [Licq v0.%d].\n", L_BLANKxSTR, 
    1086              u->GetAlias(), checkUin, licqVersion); 
     1220             u->GetAlias(), nUin, licqVersion); 
    10871221        else 
    10881222          gLog.Info("%sContact list from %s (%ld).\n", L_BLANKxSTR, u->GetAlias(), 
    1089              checkUin); 
     1223             nUin); 
    10901224 
    10911225        CEventContactList *e = CEventContactList::Parse(message, ICQ_CMDxTCP_START, TIME_NOW, nMask); 
     
    11161250          if (Ignore(IGNORE_NEWUSERS)) 
    11171251          { 
    1118             RejectEvent(checkUin, e); 
     1252            RejectEvent(nUin, e); 
    11191253            break; 
    11201254          } 
     
    11411275        if (licqChar == 'L') 
    11421276          gLog.Info("%sChat request from %s (%ld) [Licq v0.%d].\n", L_TCPxSTR, 
    1143              u->GetAlias(), checkUin, licqVersion); 
     1277             u->GetAlias(), nUin, licqVersion); 
    11441278        else 
    11451279          gLog.Info("%sChat request from %s (%ld).\n", L_TCPxSTR, u->GetAlias(), 
    1146              checkUin); 
     1280             nUin); 
    11471281 
    11481282        // translating string with translation table 
     
    11561290          if (Ignore(IGNORE_NEWUSERS)) 
    11571291          { 
    1158             RejectEvent(checkUin, e); 
     1292            RejectEvent(nUin, e); 
    11591293            break; 
    11601294          } 
     
    11671301        break; 
    11681302      } 
     1303 
     1304      // File transfer 
    11691305      case ICQ_CMDxSUB_FILE: 
    11701306      { 
     
    11831319        if (licqChar == 'L') 
    11841320          gLog.Info("%sFile transfer request from %s (%ld) [Licq v0.%d].\n", 
    1185              L_TCPxSTR, u->GetAlias(), checkUin, licqVersion); 
     1321             L_TCPxSTR, u->GetAlias(), nUin, licqVersion); 
    11861322        else 
    11871323          gLog.Info("%sFile transfer request from %s (%ld).\n", L_TCPxSTR, 
    1188              u->GetAlias(), checkUin); 
     1324             u->GetAlias(), nUin); 
    11891325 
    11901326        // translating string with translation table 
     
    11981334          if (Ignore(IGNORE_NEWUSERS)) 
    11991335          { 
    1200             RejectEvent(checkUin, e); 
     1336            RejectEvent(nUin, e); 
    12011337            break; 
    12021338          } 
     
    12091345        break; 
    12101346      } 
     1347 
     1348      // Encryption key request 
     1349      case ICQ_CMDxSUB_KEYxREQUEST: 
     1350      { 
     1351#ifdef USE_OPENSSL 
     1352        if (nInVersion <= 4) packet >> theSequence; 
     1353        else packet >> junkLong >> junkLong; 
     1354        packet >> licqChar >> licqVersion; 
     1355 
     1356        if (licqChar == 'L') 
     1357          gLog.Info("%sSecure key request from %s (%ld) [Licq v0.%d].\n", 
     1358           L_TCPxSTR, u->GetAlias(), nUin, licqVersion); 
     1359        else 
     1360          gLog.Info("%sSecure key request from %s (%ld).\n", L_TCPxSTR, 
     1361           u->GetAlias(), nUin); 
     1362 
     1363        CDHKey *k = pSock->DHKey(); 
     1364        if (k == NULL) 
     1365        { 
     1366          k = pSock->CreateDHKey(); 
     1367        } 
     1368        else if (k->CryptoStatus() == CRYPTO_FULL) 
     1369        { 
     1370          u->SetSecure(false); 
     1371          pSock->ClearDHKey(); 
     1372          k = pSock->CreateDHKey(); 
     1373        } 
     1374 
     1375        // we have a g, g^a, p 
     1376        BIGNUM *b, *g, *ga, *p, *gb, *gab; 
     1377        b = BN_new(); 
     1378        g = BN_new(); 
     1379        ga = BN_new(); 
     1380        p = BN_new(); 
     1381        gb = BN_new(); 
     1382        gab = BN_new(); 
     1383        char cg[9] = {0}, cga[128] = {0}, cp[128] = {0}, cgb[128] = {0}; 
     1384        BN_CTX *temp_ctx = BN_CTX_new (); 
     1385        sscanf(message, "%s\n%s\n%s", cg, cga, cp); 
     1386        gLog.Info("[CRPT] got [%s]\n[%s]\n[%s]\n", cg, cga, cp); 
     1387        /* FIXME OPENSSL can we get rid of this ? 
     1388          strncpy (cg, (const char *) szMessage + 5, 8); 
     1389          strncpy (cga, (const char *) szMessage + 13, 8); 
     1390          strncpy (cp, (const char *) szMessage + 21, 8); 
     1391        */ 
     1392        BN_hex2bn (&g, cg); 
     1393        BN_hex2bn (&ga, cga); 
     1394        BN_hex2bn (&p, cp); 
     1395 
     1396        // now we get a random b, and make g^ab 
     1397        BN_rand (b, 192, 0, 127); 
     1398        BN_mod_exp (gab, ga, b, p, temp_ctx); 
     1399        BN_mod_exp (gb, g, b, p, temp_ctx); 
     1400 
     1401        // Now, lets see how this happened 
     1402        // If we hadn't sent anything yet, eat their key, and reply accordingly, 
     1403        // or if we have sent already, compare his prime to mine.  If his is 
     1404        // larger, then we'll use his.  I'll eat his key, and reply accordingly. 
     1405        if ((k->CryptoStatus() == CRYPTO_NONE) || 
     1406            ((k->CryptoStatus() == CRYPTO_HALF) && (BN_cmp(k->P(), p) == 1)) ) 
     1407        { 
     1408          BN_copy(k->P(), p); 
     1409          BN_copy(k->A(), b); 
     1410          BN_copy(k->G(), ga); 
     1411          BN_copy(k->GAB(), gab); 
     1412 
     1413          if (k->CryptoStatus() == CRYPTO_HALF) 
     1414          { 
     1415            gLog.Info("[CRPT] I already sent, but I'm using %s's key.\n", 
     1416               u->GetAlias()); 
     1417          } 
     1418 
     1419          // send gab 
     1420          strcpy(cgb, BN_bn2hex (gb)); 
     1421          CPT_AckKey p(theSequence, cgb, u); 
     1422          AckTCP(p, pSock); 
     1423 
     1424          k->SetCryptoStatus(CRYPTO_FULL); 
     1425          //pSock->SetDHKey(k); 
     1426          u->SetSecure(true); 
     1427          gLog.Info("\t[Sent g^b]:\n[%s]\n", BN_bn2hex(gb)); 
     1428        } 
     1429 
     1430        // Clean up 
     1431        BN_CTX_free (temp_ctx); 
     1432        BN_clear_free (p); 
     1433        BN_clear_free (b); 
     1434        BN_clear_free (ga); 
     1435        BN_clear_free (gb); 
     1436        BN_clear_free (gab); 
     1437 
     1438        gLog.Info("[CRPT] Shared Key with %s(g^(gab)):\n[%s]\n", u->GetAlias(), 
     1439           BN_bn2hex(k->GAB())); 
     1440 
     1441        break; 
     1442 
     1443#else // We do not support OpenSSL 
     1444        gLog.Info("%sReceived key request from %s (%ld) but we do not support OpenSSL.\n", 
     1445           L_TCPxSTR, u->GetAlias(), nUin); 
     1446        // Send the nack back 
     1447        CPT_AckKey p(theSequence, "", u); 
     1448        AckTCP(p, pSock); 
     1449        break; 
     1450#endif 
     1451      } 
     1452 
    12111453 
    12121454      default: 
     
    12331475    switch (newCommand) 
    12341476    { 
    1235     case ICQ_CMDxSUB_MSG: 
    1236     case ICQ_CMDxTCP_READxNAxMSG: 
    1237     case ICQ_CMDxTCP_READxDNDxMSG: 
    1238     case ICQ_CMDxTCP_READxOCCUPIEDxMSG: 
    1239     case ICQ_CMDxTCP_READxAWAYxMSG: 
    1240     case ICQ_CMDxTCP_READxFFCxMSG: 
    1241     case ICQ_CMDxSUB_URL: 
    1242     case ICQ_CMDxSUB_CONTACTxLIST: 
    1243       if (nInVersion <= 4) packet >> theSequence; 
    1244       else packet >> junkLong >> junkLong; 
    1245       packet >> licqChar >> licqVersion; 
    1246       break; 
    1247  
    1248     case ICQ_CMDxSUB_CHAT: 
    1249     { 
    1250       char ul[1024]; 
    1251       packet.UnpackString(ul); 
    1252       packet >> nPortReversed   // port backwards 
    1253              >> nPort;    // port to connect to for chat 
    1254       if (nInVersion <= 4) packet >> theSequence; 
    1255       packet >> licqChar >> licqVersion; 
    1256  
    1257       if (nPort == 0) nPort = (nPortReversed >> 8) | ((nPortReversed & 0xFF) << 8); 
    1258       // only if this is the first chat ack packet do we do anything 
    1259       if (s_nChatSequence == theSequence && s_nChatUin == checkUin) 
    1260       { 
     1477      case ICQ_CMDxSUB_MSG: 
     1478      case ICQ_CMDxTCP_READxNAxMSG: 
     1479      case ICQ_CMDxTCP_READxDNDxMSG: 
     1480      case ICQ_CMDxTCP_READxOCCUPIEDxMSG: 
     1481      case ICQ_CMDxTCP_READxAWAYxMSG: 
     1482      case ICQ_CMDxTCP_READxFFCxMSG: 
     1483      case ICQ_CMDxSUB_URL: 
     1484      case ICQ_CMDxSUB_CONTACTxLIST: 
     1485        if (nInVersion <= 4) packet >> theSequence; 
     1486        else packet >> junkLong >> junkLong;