Beispiel #1
0
EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
	{
	if (iIssuerName != NULL) //just to check cert is uninitialised
		{
		User::Leave(KErrArgument);
		}
	iKeyFactory = new(ELeave) TX509KeyFactory;
	
	TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
	HBufC8* temp= HBufC8::NewLC(len);	
	TPtr8 ptr=temp->Des();
	aStream.ReadL(ptr,len);
	iEncoding=temp->AllocL();
	CleanupStack::PopAndDestroy(); // temp

	TASN1DecSequence encSeq;
	TInt pos = 0;
	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
	TASN1DecGeneric* encSigAlg = seq->At(1);
	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
	TASN1DecBitString encBS;
	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
	CleanupStack::PopAndDestroy();//seq	

	CSHA1* hash = CSHA1::NewL();
	CleanupStack::PushL(hash);
	iFingerprint = hash->Final(Encoding()).AllocL();
	CleanupStack::PopAndDestroy();//hash

	ConstructCertL();
	}
void EncoreBootImage::prepareImageHeader(boot_image_header_t & header)
{
	// get identifier for the first bootable section
	Section * firstBootSection = findFirstBootableSection();
	section_id_t firstBootSectionID = 0;
	if (firstBootSection)
	{
		firstBootSectionID = firstBootSection->getIdentifier();
	}
	
	// fill in header fields
	header.m_signature[0] = 'S';
	header.m_signature[1] = 'T';
	header.m_signature[2] = 'M';
	header.m_signature[3] = 'P';
	header.m_majorVersion = ROM_BOOT_IMAGE_MAJOR_VERSION;
	header.m_minorVersion = ROM_BOOT_IMAGE_MINOR_VERSION;
	header.m_flags = ENDIAN_HOST_TO_LITTLE_U16(m_headerFlags);
	header.m_imageBlocks = ENDIAN_HOST_TO_LITTLE_U32(getImageSize());
	header.m_firstBootableSectionID = ENDIAN_HOST_TO_LITTLE_U32(firstBootSectionID);
	header.m_keyCount = ENDIAN_HOST_TO_LITTLE_U16((uint16_t)m_keys.size());
	header.m_headerBlocks = ENDIAN_HOST_TO_LITTLE_U16((uint16_t)numberOfCipherBlocks(sizeof(header)));
	header.m_sectionCount = ENDIAN_HOST_TO_LITTLE_U16((uint16_t)m_sections.size());
	header.m_sectionHeaderSize = ENDIAN_HOST_TO_LITTLE_U16((uint16_t)numberOfCipherBlocks(sizeof(section_header_t)));
	header.m_signature2[0] = 's';
	header.m_signature2[1] = 'g';
	header.m_signature2[2] = 't';
	header.m_signature2[3] = 'l';
	header.m_timestamp = ENDIAN_HOST_TO_LITTLE_U64(getTimestamp());
	header.m_driveTag = m_driveTag;

	// Prepare version fields by converting them to the correct byte order.
	header.m_productVersion = m_productVersion;
	header.m_componentVersion = m_componentVersion;
	header.m_productVersion.fixByteOrder();
	header.m_componentVersion.fixByteOrder();

	// the fields are dependant on others
	header.m_keyDictionaryBlock = ENDIAN_HOST_TO_LITTLE_U16(header.m_headerBlocks + header.m_sectionCount * header.m_sectionHeaderSize);
	header.m_firstBootTagBlock = ENDIAN_HOST_TO_LITTLE_U32(header.m_keyDictionaryBlock + header.m_keyCount * 2);
	
	// generate random pad bytes
	RandomNumberGenerator rng;
	rng.generateBlock(header.m_padding0, sizeof(header.m_padding0));
	rng.generateBlock(header.m_padding1, sizeof(header.m_padding1));
	
	// compute SHA-1 digest over the image header
	uint8_t * message = reinterpret_cast<uint8_t *>(&header.m_signature);
	uint32_t length = static_cast<uint32_t>(sizeof(header) - sizeof(header.m_digest)); // include padding
	
	CSHA1 hash;
	hash.Reset();
	hash.Update(message, length);
	hash.Final();
	hash.GetHash(header.m_digest);
}
Beispiel #3
0
void Connection::scramble(const char *_scramble1, const char *_scramble2, UINT8 _outToken[20])
{
  std::string seed;
  seed += _scramble1;
  seed += _scramble2;

  CSHA1 passdg;
  UINT8 stage1_hash[20];
  passdg.Update ( (UINT8 *) m_password.c_str(), m_password.size());
  passdg.Final();
  passdg.GetHash(stage1_hash);


  CSHA1 stage2dg;
  UINT8 stage2_hash[20];
  stage2dg.Update (stage1_hash, 20);
  stage2dg.Final();
  stage2dg.GetHash(stage2_hash);

  CSHA1 finaldg;
  UINT8 final_hash[20];
  finaldg.Update( (UINT8*) seed.c_str(), seed.size());
  finaldg.Update(stage2_hash, 20);
  finaldg.Final();
  finaldg.GetHash(final_hash);

  for (int index = 0; index < 20; index ++)
  {
    _outToken[index] = final_hash[index] ^ stage1_hash[index]; 
  }
}
Beispiel #4
0
CHashSHA1 CBENode::GetSHA1() const
{
	ASSERT( this != NULL );

	CBuffer pBuffer;
	Encode( &pBuffer );

	CSHA1 pDigest;
	pDigest.Add( pBuffer.m_pBuffer, pBuffer.m_nLength );
	pDigest.Finish();
	return pDigest;
}
Beispiel #5
0
string sha1(const string& input)
{
    SHA1.Reset();
    SHA1.Update((unsigned char *)input.c_str(), input.size());
    SHA1.Final();
    unsigned char uResult[20];
    SHA1.GetHash(uResult);

    BYTEARRAY MapSHA1 = UTIL_CreateByteArray( uResult, 20 );
    string sResult = UTIL_ByteArrayToHexStringWithoutSpaces(MapSHA1);

    return sResult;
}
// -----------------------------------------------------------------------------
// RoapStorageClient::GetDevicePublicKeyHashL
// -----------------------------------------------------------------------------
//
EXPORT_C TInt Roap::RRoapStorageClient::GetDevicePublicKeyHashL( TDes8& aHash )
    {
    CSHA1* hash = NULL;
    HBufC8* key = NULL;

    GetDevicePublicKeyDerL( key );
    CleanupStack::PushL( key );
    hash = CSHA1::NewL();
    CleanupStack::PushL( hash );
    hash->Hash( *key );
    aHash.Copy( hash->Final() );
    CleanupStack::PopAndDestroy( hash );
    CleanupStack::PopAndDestroy( key );
    return KErrNone;
    }
Beispiel #7
0
static void
print_sha1 (ImageInput *input)
{
    imagesize_t size = input->spec().image_bytes ();
    if (size >= std::numeric_limits<size_t>::max()) {
        printf ("    SHA1 digest: (unable to compute, image is too big)\n");
        return;
    }
    boost::scoped_array<unsigned char> buf(new unsigned char[(unsigned int)size]);
    input->read_image (input->spec().format, &buf[0]);
    CSHA1 sha;
    sha.Update ((const unsigned char *)&buf[0], (unsigned int) size);
    sha.Final ();
    std::string digest;
    sha.ReportHashStl (digest, CSHA1::REPORT_HEX_SHORT);
    printf ("    SHA-1: %s\n", digest.c_str());
}
string generateSHA(string& value)
{
	CSHA1 sha;

	sha.Update((UINT_8*)value.c_str(), value.length());

	sha.Final();

	UINT_8 digest[20];
	if (sha.GetHash(digest))
	{
		const int size = sizeof(digest) / sizeof(UINT_8);
		return binToHex((char*)digest, size);
	}

	return "";
}
Beispiel #9
0
void TorrentFile::CreateInfoHash() {
	if(info_len == 0) return;
	CSHA1 sha;

	unsigned char * info  = new unsigned char[info_len];
	for(int i = 0; i < info_len; i++) {
		info[i] = (unsigned char)m_data[info_start+i];
	}
	sha.Update(info, info_len);
	sha.Final();
	unsigned char * temp = new unsigned char[256];
	
	sha.GetHash(temp);
	char retStr[61];
	retStr[0] = 0;
	char szTemp[4];
	char c[2];
	c[1] = 0;
	for(int i = 0; i < 20; i++) {
		sprintf(szTemp, "%u", temp[i]);
		int value = atoi(szTemp);
		m_info_hash[i] = value;
		if((value > 0 && value < 255) && (isalnum(value))) {
			c[0] = value;
			strcat(retStr, c);
		}
		else {
			c[0] = '%';
			strcat(retStr, c);
			if(value < 16) strcat(retStr, "0");
			itoa(value, szTemp, 16);
			strcat(retStr, szTemp);
		}
	}

	retStr[60] = 0;
	m_info_hash_string = retStr;
	delete [] info;
	info = NULL;
	delete [] temp;

}
Beispiel #10
0
void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
	{
	TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
	gen.InitL();
	
	// The outermost tag for X509 certificates is always a sequence.
	// Since this tag does not form part of the signed data it is possible
	// to corrupt the tag by changing it to any other ASN.1 tag and process
	// the rest of the certificate as normal.
	// However, we still reject the certificate anyway to avoid 
	// confusion because the data does not match the X.509 specification.	
	if (gen.Tag() != EASN1Sequence)
		{
		User::Leave(KErrArgument);
		}
	
	aPos += gen.LengthDER();
	iKeyFactory = new(ELeave) TX509KeyFactory;

	iEncoding = gen.Encoding().AllocL();

	TASN1DecSequence encSeq;
	TInt pos = 0;
	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
	TASN1DecGeneric* encSigAlg = seq->At(1);
	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
	TASN1DecBitString encBS;
	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
	CleanupStack::PopAndDestroy();//seq

	CSHA1* hash = CSHA1::NewL();
	CleanupStack::PushL(hash);
	iFingerprint = hash->Final(Encoding()).AllocL();
	CleanupStack::PopAndDestroy();//hash
	ConstructCertL();
	}
 CCData *TimeHashVerifier::encode_verification(CCString *private_key, CCString *public_key, CCString *secret_key) {
     time_t now = this->time_gen(NULL);
     CSHA1 hexhash;
     char timehex[9] = {0,};
     sprintf(timehex, "%08lx", now);
     hexhash.Update((UINT_8 *)private_key->getCString(), private_key->length());
     hexhash.Update((UINT_8 *)public_key->getCString(), public_key->length());
     hexhash.Update((UINT_8 *)timehex, 8);
     hexhash.Final();
     unsigned char hexhashbin[20];
     hexhash.GetHash(hexhashbin);
     char hexhashhex[41] = {0,};
     for (int i = 0; i < 20; i++) {
         sprintf(hexhashhex + i * 2, "%02x", hexhashbin[i]);
     }
     int verification_len = public_key->length() + 1 + 8 + 40;
     char verification[verification_len + 1];
     bzero(verification, verification_len + 1);
     sprintf(verification, "%s$%8lx%s", public_key->getCString(), now, hexhashhex);
     CCData *data = new CCData(new CCData((unsigned char *)verification, verification_len));
     //data->autorelease();
     return data;
 }
Beispiel #12
0
void sha1 (uint8_t* dest, const uint8_t* src, size_t n) {
	CSHA1 hash;
	hash.Write(src, n);
	hash.Finalize(dest);
}
//! \todo Optimize writing section data. Right now it only writes one block at a
//!		time, which is of course quite slow (in relative terms).
//!	\todo Refactor this into several different methods for writing each region
//!		of the image. Use a context structure to keep track of shared data between
//!		each of the methods.
//! \todo Refactor the section and boot tag writing code to only have a single
//!		copy of the block writing and encryption loop.
void EncoreBootImage::writeToStream(std::ostream & stream)
{
	// always generate the session key or DEK even if image is unencrypted
	m_sessionKey.randomize();
	
	// prepare to compute CBC-MACs with each KEK
	unsigned i;
	smart_array_ptr<RijndaelCBCMAC> macs(0);
	if (isEncrypted())
	{
		macs = new RijndaelCBCMAC[m_keys.size()];
		for (i=0; i < m_keys.size(); ++i)
		{
			RijndaelCBCMAC mac(m_keys[i]);
			(macs.get())[i] = mac;
		}
	}
	
	// prepare to compute SHA-1 digest over entire image
	CSHA1 hash;
	hash.Reset();
	
	// count of total blocks written to the file
	unsigned fileBlocksWritten = 0;

	// we need some pieces of the header down below
	boot_image_header_t imageHeader;
	prepareImageHeader(imageHeader);
	
	// write plaintext header
	{
		// write header
		assert(sizeOfPaddingForCipherBlocks(sizeof(boot_image_header_t)) == 0);
		stream.write(reinterpret_cast<char *>(&imageHeader), sizeof(imageHeader));
		fileBlocksWritten += numberOfCipherBlocks(sizeof(imageHeader));
		
		// update CBC-MAC over image header
		if (isEncrypted())
		{
			for (i=0; i < m_keys.size(); ++i)
			{
				(macs.get())[i].update(reinterpret_cast<uint8_t *>(&imageHeader), sizeof(imageHeader));
			}
		}
		
		// update SHA-1
		hash.Update(reinterpret_cast<uint8_t *>(&imageHeader), sizeof(imageHeader));
	}
	
	// write plaintext section table
	{
		section_iterator_t it = beginSection();
		for (; it != endSection(); ++it)
		{
			Section * section = *it;
			
			// write header for this section
			assert(sizeOfPaddingForCipherBlocks(sizeof(section_header_t)) == 0);
			section_header_t sectionHeader;
			section->fillSectionHeader(sectionHeader);
			stream.write(reinterpret_cast<char *>(&sectionHeader), sizeof(sectionHeader));
			fileBlocksWritten += numberOfCipherBlocks(sizeof(sectionHeader));
			
			// update CBC-MAC over this entry
			if (isEncrypted())
			{
				for (i=0; i < m_keys.size(); ++i)
				{
					(macs.get())[i].update(reinterpret_cast<uint8_t *>(&sectionHeader), sizeof(sectionHeader));
				}
			}
			
			// update SHA-1
			hash.Update(reinterpret_cast<uint8_t *>(&sectionHeader), sizeof(sectionHeader));
		}
	}
	
	// finished with the CBC-MAC
	if (isEncrypted())
	{
		for (i=0; i < m_keys.size(); ++i)
		{
			(macs.get())[i].finalize();
		}
	}
	
	// write key dictionary
	if (isEncrypted())
	{
		key_iterator_t it = beginKeys();
		for (i=0; it != endKeys(); ++it, ++i)
		{
			// write CBC-MAC result for this key, then update SHA-1
			RijndaelCBCMAC & mac = (macs.get())[i];
			const RijndaelCBCMAC::block_t & macResult = mac.getMAC();
			stream.write(reinterpret_cast<const char *>(&macResult), sizeof(RijndaelCBCMAC::block_t));
			hash.Update(reinterpret_cast<const uint8_t *>(&macResult), sizeof(RijndaelCBCMAC::block_t));
			fileBlocksWritten++;
			
			// encrypt DEK with this key, write it out, and update image digest
			Rijndael cipher;
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, *it, Rijndael::Key16Bytes, imageHeader.m_iv);
			AESKey<128>::key_t wrappedSessionKey;
			cipher.blockEncrypt(m_sessionKey, sizeof(AESKey<128>::key_t) * 8, wrappedSessionKey);
			stream.write(reinterpret_cast<char *>(&wrappedSessionKey), sizeof(wrappedSessionKey));
			hash.Update(reinterpret_cast<uint8_t *>(&wrappedSessionKey), sizeof(wrappedSessionKey));
			fileBlocksWritten++;
		}
	}
	
	// write sections and boot tags
	{
		section_iterator_t it = beginSection();
		for (; it != endSection(); ++it)
		{
			section_iterator_t itCopy = it;
			bool isLastSection = (++itCopy == endSection());
			
			Section * section = *it;
			cipher_block_t block;
			unsigned blockCount = section->getBlockCount();
			unsigned blocksWritten = 0;
			
			Rijndael cipher;
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			
			// Compute the number of padding blocks needed to align the section. This first
			// call to getPadBlockCountForOffset() passes an offset that excludes
			// the boot tag for this section.
			unsigned paddingBlocks = getPadBlockCountForSection(section, fileBlocksWritten);
			
			// Insert nop commands as padding to align the start of the section, if
			// the section has special alignment requirements.
			NopCommand nop;
			while (paddingBlocks--)
			{
				blockCount = nop.getBlockCount();
				blocksWritten = 0;
				while (blocksWritten < blockCount)
				{
					nop.getBlocks(blocksWritten, 1, &block);
					
					if (isEncrypted())
					{
						// re-init after encrypt to update IV
						cipher.blockEncrypt(block, sizeof(cipher_block_t) * 8, block);
						cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, block);
					}
					
					stream.write(reinterpret_cast<char *>(&block), sizeof(cipher_block_t));
					hash.Update(reinterpret_cast<uint8_t *>(&block), sizeof(cipher_block_t));
					
					blocksWritten++;
					fileBlocksWritten++;
				}
			}
			
			// reinit cipher for boot tag
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			
			// write boot tag
			TagCommand tag(*section);
			tag.setLast(isLastSection);
			if (!isLastSection)
			{
				// If this isn't the last section, the tag needs to include any
				// padding for the next section in its length, otherwise the ROM
				// won't be able to find the next section's boot tag.
				unsigned nextSectionOffset = fileBlocksWritten + section->getBlockCount() + 1;
				tag.setSectionLength(section->getBlockCount() + getPadBlockCountForSection(*itCopy, nextSectionOffset));
			}
			blockCount = tag.getBlockCount();
			blocksWritten = 0;
			while (blocksWritten < blockCount)
			{
				tag.getBlocks(blocksWritten, 1, &block);
				
				if (isEncrypted())
				{
					// re-init after encrypt to update IV
					cipher.blockEncrypt(block, sizeof(cipher_block_t) * 8, block);
					cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, block);
				}
				
				stream.write(reinterpret_cast<char *>(&block), sizeof(cipher_block_t));
				hash.Update(reinterpret_cast<uint8_t *>(&block), sizeof(cipher_block_t));
				
				blocksWritten++;
				fileBlocksWritten++;
			}
			
			// reinit cipher for section data
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			
			// write section data
			blockCount = section->getBlockCount();
			blocksWritten = 0;
			while (blocksWritten < blockCount)
			{
				section->getBlocks(blocksWritten, 1, &block);
				
				// Only encrypt the section contents if the entire boot image is encrypted
				// and the section doesn't have the "leave unencrypted" flag set. Even if the
				// section is unencrypted the boot tag will remain encrypted.
				if (isEncrypted() && !section->getLeaveUnencrypted())
				{
					// re-init after encrypt to update IV
					cipher.blockEncrypt(block, sizeof(cipher_block_t) * 8, block);
					cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, block);
				}
				
				stream.write(reinterpret_cast<char *>(&block), sizeof(cipher_block_t));
				hash.Update(reinterpret_cast<uint8_t *>(&block), sizeof(cipher_block_t));
				
				blocksWritten++;
				fileBlocksWritten++;
			}
		}
	}
	
	// write SHA-1 digest over entire image
	{
		// allocate enough room for digest and bytes to pad out to the next cipher block
		const unsigned padBytes = sizeOfPaddingForCipherBlocks(sizeof(sha1_digest_t));
		unsigned digestBlocksSize = sizeof(sha1_digest_t) + padBytes;
		smart_array_ptr<uint8_t> digestBlocks = new uint8_t[digestBlocksSize];
		hash.Final();
		hash.GetHash(digestBlocks.get());
		
		// set the pad bytes to random values
		RandomNumberGenerator rng;
		rng.generateBlock(&(digestBlocks.get())[sizeof(sha1_digest_t)], padBytes);
		
		// encrypt with session key
		if (isEncrypted())
		{
			Rijndael cipher;
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			cipher.blockEncrypt(digestBlocks.get(), digestBlocksSize * 8, digestBlocks.get());
		}
		
		// write to the stream
		stream.write(reinterpret_cast<char *>(digestBlocks.get()), digestBlocksSize);
	}
}
Beispiel #14
0
// Thread which gets lines from the DCC Q, and processes it.
void DCCThr(XChange *XGlobal) {
char IRC_Line[1024];
IRCLineInterpret LineInterpret;
TCPConnect *DCCChat, *FServChat, *DCCAccept, *SwarmConnect;
DCC_Container_t *DCC_Container;
THR_EXITCODE thr_exit = 1;
THR_HANDLE DCCChatThrH = 0, FileServerThrH = 0, TransferThrH = 0;
bool retvalb;
int retval;
char MyNick[64];
LineParse LineP;
const char *parseptr;
char *tmpbuf;
CSHA1 SHA;
FilesDetail *FD;
char Response[1024];
Helper H;
TCPConnect T; // Just for a little help.
THREADID tempTID;
size_t my_resume_position;
char DotIp[20]; // cant be more than 3 + 1 + 3 + 1 + 3 + 1 + 3
int SwarmIndex;
bool isSwarmed;

   TRACE_INIT_CRASH("DCCThr");
   TRACE();
   H.init(XGlobal);
   while (true) {
      XGlobal->IRC_DCC.getLineAndDelete(IRC_Line);
      if (XGlobal->isIRC_QUIT()) break;
      if (XGlobal->isIRC_DisConnected()) continue;

      LineInterpret = IRC_Line;
      switch (LineInterpret.Command) {

        case IC_CTCPFILESHA1REPLY:
           // Compare FileName, FileSize, SHA1 and update Server UI.
           // If FileSize = 0 and SHA1 = 0, => error string present in FileName
           XGlobal->lock();
           if ( (XGlobal->SHA1_FileName) &&
                (XGlobal->SHA1_SHA1) &&
                (strcasecmp(LineInterpret.FileName, XGlobal->SHA1_FileName) == 0) &&
                (LineInterpret.FileSize == XGlobal->SHA1_FileSize) ) {
              // Reply matches what we are waiting for.
              // Compare SHAs
              if (strcasecmp(XGlobal->SHA1_SHA1, LineInterpret.InfoLine) == 0) {
                 sprintf(Response, "Server 04[%s FILECHECK REPLY]: \"%s\" can be resumed from me", LineInterpret.From.Nick, LineInterpret.FileName);
              }
              else {
                 sprintf(Response, "Server 04[%s FILECHECK REPLY]: \"%s\" CANNOT be resumed from me", LineInterpret.From.Nick, LineInterpret.FileName);
              }
              // Delete the Global as we are done with this.
              delete [] XGlobal->SHA1_FileName;
              XGlobal->SHA1_FileName = NULL;
              delete [] XGlobal->SHA1_SHA1;
              XGlobal->SHA1_SHA1 = NULL;
           }
           else {
              sprintf(Response, "Server 04[%s FILECHECK REPLY]: %s", LineInterpret.From.Nick, LineInterpret.FileName);
           }
           XGlobal->unlock();
           XGlobal->IRC_ToUI.putLine(Response);
           break;

        case IC_CTCPFILESHA1:
           // Reply back to his request with a IC_CTCPFILESHA1REPLY
           // Same thing that we did in the UI to generate IC_CTCPFILESHA1
           // Here we will search for the file in MyFilesDB. If not found
           // there, we use MyPartialFilesDB.
           FD = XGlobal->MyFilesDB.getFilesDetailListMatchingFileName(LineInterpret.FileName);
           if (FD == NULL) {
              // Lets try MyPartialFilesDB.
              FD = XGlobal->MyPartialFilesDB.getFilesDetailListMatchingFileName(LineInterpret.FileName);
              if (FD == NULL) {
                 sprintf(Response, "Server 04[%s FILECHECK]: File: %s FileSize: %lu - We do not have this file.", LineInterpret.From.Nick, LineInterpret.FileName, LineInterpret.FileSize);
                 XGlobal->IRC_ToUI.putLine(Response);
                 sprintf(Response, "NOTICE %s :\001FILESHA1 0 0 I do not have the file requested: %s\001", LineInterpret.From.Nick, LineInterpret.FileName);
                 XGlobal->IRC_ToServer.putLine(Response);
                 break;
              }
              else {
                 // File in MyPartialFilesDB. Prepare filename in Response
                 XGlobal->lock();
                 sprintf(Response, "%s%s%s", XGlobal->PartialDir, DIR_SEP, LineInterpret.FileName);
                 XGlobal->unlock();
              }
           }
           else {
              // File in MyFilesDB. Prepare filename in Response
              XGlobal->lock();
              if (FD->DirName) {
                 sprintf(Response, "%s%s%s%s%s", XGlobal->ServingDir[FD->ServingDirIndex], DIR_SEP, FD->DirName, DIR_SEP, LineInterpret.FileName);
              }
              else {
                 sprintf(Response, "%s%s%s", XGlobal->ServingDir[FD->ServingDirIndex], DIR_SEP, LineInterpret.FileName);
              }
              XGlobal->unlock();
           }

           XGlobal->MyFilesDB.freeFilesDetailList(FD);
           FD = NULL;

           // we are here => Response has full file path.
           tmpbuf = new char[FILE_RESUME_GAP];
           if (getFileResumeChunk(Response, LineInterpret.FileSize, tmpbuf) == false) {
              sprintf(Response, "Server 04[%s FILECHECK]: File: %s FileSize: %lu - Error Reading Chunk.", LineInterpret.From.Nick, LineInterpret.FileName, LineInterpret.FileSize);
              XGlobal->IRC_ToUI.putLine(Response);
              sprintf(Response, "NOTICE %s :\001FILESHA1 0 0 Error reading chunk: %s\001", LineInterpret.From.Nick, LineInterpret.FileName);
              XGlobal->IRC_ToServer.putLine(Response);
              delete [] tmpbuf;
              break;
           }

           SHA.Reset();
           SHA.Update((UINT_8 *) tmpbuf, (UINT_32) FILE_RESUME_GAP);
           SHA.Final();
           SHA.ReportHash(tmpbuf);

           sprintf(Response, "Server 04[%s FILECHECK]: File: %s FileSize: %lu.", LineInterpret.From.Nick, LineInterpret.FileName, LineInterpret.FileSize);
           XGlobal->IRC_ToUI.putLine(Response);
           sprintf(Response, "NOTICE %s :\001FILESHA1 %lu %s %s\001",
                    LineInterpret.From.Nick,
                    LineInterpret.FileSize,
                    tmpbuf,
                    LineInterpret.FileName);
           XGlobal->IRC_ToServer.putLine(Response);
           delete [] tmpbuf;

           break;

        case IC_USERHOST:
           char windowname[32];
           unsigned long longip, myip;
           char *correct_nick;
           COUT(cout << "IC_USERHOST: IRCLine: " << IRC_Line << endl;)
           COUT(LineInterpret.printDebug();)
//      InfoLine contains: [email protected]
//      batata_wada*[email protected] (ircop)
//         We parse it nice and update XGlobal with dotted ip and long ip
//         if its our nick, and update NickList with long ip.

           LineP = LineInterpret.InfoLine;
           LineP.setDeLimiter('@');
           parseptr = LineP.getWord(2);
           longip = T.getLongFromHostName((char *) parseptr);
           T.getDottedIpAddressFromLong(longip, DotIp);

           // Lets get our nick.
           XGlobal->getIRC_Nick(MyNick);
           XGlobal->resetIRC_Nick_Changed();
           LineP.setDeLimiter('=');
           parseptr = LineP.getWord(1);
           correct_nick = new char[strlen(parseptr) + 1];
           strcpy(correct_nick, parseptr);
           if (correct_nick[strlen(correct_nick) - 1] == '*') {
              // Remove the * at end of ircop nick.
              correct_nick[strlen(correct_nick) - 1] = '\0';
           }
           // correct_nick contains corrected nick.

           if (strcasecmp(correct_nick, MyNick) == 0) {
              // Its my own Nick
              XGlobal->putIRC_IP(longip, DotIp);
              sprintf(Response, "Server 09USERHOST: DottedIP: %s LongIP: %lu", DotIp, longip);
              XGlobal->IRC_ToUI.putLine(Response);
           }

           // Update the XGlobal->NickList
           XGlobal->NickList.setNickIP(correct_nick, longip);

           // For testing.
           if (longip != 0) {
              sprintf(Response, "Server 09USERHOST: Nick: %s DottedIP: %s LongIP: %lu", correct_nick, DotIp, longip);
           } 
           else {
              sprintf(Response, "Server 04USERHOST: Nick: %s DottedIP: %s LongIP: %lu", correct_nick, DotIp, longip);
           }
           XGlobal->IRC_ToUI.putLine(Response);

           // If the USERHOST response is of Nick which is same as in
           // XChange->DCCChatnick, then we need to try to Chat with this nick.
           retval = 1;
           XGlobal->lock();
           if (XGlobal->DCCChatNick) {
              retval = strcasecmp(correct_nick, XGlobal->DCCChatNick);
           }
           XGlobal->unlock();

           if (retval == 0) {
              FilesDetail *FD;

              XGlobal->lock();
              delete [] XGlobal->DCCChatNick;
              XGlobal->DCCChatNick = NULL;
              XGlobal->unlock();

              // Check if a DCCChat is already in progress. (allow only 1)
              if (XGlobal->DCCChatInProgress.getCount(NULL) != 0) {
                 sprintf(Response, "Server * 04DCC-CHAT: A CHAT is already in progress.");
                 XGlobal->IRC_ToUI.putLine(Response);
                 delete [] correct_nick;
                 break;
              }

              if (longip != 0) {
                 // Try to connect to his DCCServer as a CHAT.
                 TCPConnect *DCCChat = new TCPConnect;
                 DCCChat->TCPConnectionMethod = XGlobal->getIRC_CM();
                 XGlobal->resetIRC_CM_Changed();
                 retvalb = DCCChat->getConnection(DotIp, DCCSERVER_PORT);
                 Response[0] = '\0';
                 if (retvalb) {
                    // Connection was successful
                    sprintf(Response, "100 %s\n", MyNick);
                    DCCChat->writeData(Response, strlen(Response), DCCSERVER_TIMEOUT);
                    retval = DCCChat->readLine(Response, sizeof(Response) - 1, DCCSERVER_TIMEOUT);
                    LineP = Response;
                    parseptr = LineP.getWord(1);
                    if (retval && strcasecmp(parseptr, "101") == 0) {
                       // Now also check if the nick matches. Else he has some
                       // other client listening at that port.
                       parseptr = LineP.getWord(2);
                       if (strcasecmp(parseptr, correct_nick) == 0) {
                          // We have established a CHAT.
                          // Now we pass the buck on to the DCC Chat Thr
                          // It will add it in DCCChatInProgress etc.
                          COUT(cout << "DCCChatThr: IC_DCC_CHAT (DCC)" << endl;)
                          // Here we spawn a thread to take care of this DCC Chat.
                          // We pass it the ESTABLISED connection
                          // The created thread should free this structure before exiting.
                          DCC_Container = new DCC_Container_t;
                          DCC_CONTAINER_INIT(DCC_Container);
                          DCC_Container->RemoteNick = new char [strlen(parseptr) + 1];
                          strcpy(DCC_Container->RemoteNick, parseptr);
                          DCC_Container->Connection = DCCChat;
                          DCC_Container->XGlobal = XGlobal;

                          // Have to set DCC_Container->RemoteLongIP.
                          DCC_Container->RemoteDottedIP = new char[strlen(DotIp) + 1];
                          strcpy(DCC_Container->RemoteDottedIP, DotIp);
                          DCC_Container->RemoteLongIP = longip;

#ifdef __MINGW32__
                          DCCChatThrH = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DCCChatThr, DCC_Container, 0, &tempTID);
#else
                          {
                             pthread_attr_t thread_attr;
                             pthread_attr_init(&thread_attr);
                             pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
                             pthread_create(&DCCChatThrH, &thread_attr, (void * (*)(void *)) DCCChatThr, DCC_Container);
                          }
#endif
                          delete [] correct_nick;
                          break;
                       }