void TranslateAccountTypeToString(OTAccount::AccountType theType, OTString & strAcctType)
{
	switch (theType)
	{
		case OTAccount::simple:
			strAcctType.Set("simple");
			break;
		case OTAccount::issuer:
			strAcctType.Set("issuer");
			break;
		case OTAccount::basket:
			strAcctType.Set("basket");
			break;
		case OTAccount::basketsub:
			strAcctType.Set("basketsub");
			break;
		case OTAccount::mint:
			strAcctType.Set("mint");
			break;
		case OTAccount::voucher:
			strAcctType.Set("voucher");
			break;
		case OTAccount::stash:
			strAcctType.Set("stash");
			break;
		default:
			strAcctType.Set("err_acct");
			break;
	}
}
void OTSocket::Listen(const OTString &strBind)
{
	if (NULL != m_pSocket)
		delete m_pSocket;
//	m_pSocket = NULL;
	m_pSocket = new zmq::socket_t(*m_pContext, ZMQ_REP);  // RESPONSE socket (Request / Response.)
	OT_ASSERT_MSG(NULL != m_pSocket, "OTSocket::Listen: new zmq::socket(context, ZMQ_REP)");
	
	OTString strTemp(strBind); // In case m_strBindPath is what was passed in. (It happens.)
	m_strBindPath.Set(strTemp); // In case we have to close/reopen the socket to finish a send/receive.
	
	// ------------------------
	//  Configure socket to not wait at close time
    //
	const int linger = 0; // close immediately
	m_pSocket->setsockopt (ZMQ_LINGER, &linger, sizeof (linger));
    /*
     int zmq_setsockopt (void *socket, int option_name, const void *option_value, size_t option_len);
     
     Caution: All options, with the exception of ZMQ_SUBSCRIBE, ZMQ_UNSUBSCRIBE and ZMQ_LINGER, only take effect for subsequent socket bind/connects.     
     */
    
	// ------------------------
    
	m_pSocket->bind(strBind.Get());
}
Пример #3
0
const bool OTPaths::Win_GetInstallFolderFromRegistry(OTString & out_InstallFolderPath)
{
	WindowsRegistryTools windowsRegistryTools;




	HKEY hKey=0;
	LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Open-Transactions", 0, KEY_READ, &hKey);
	bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
	bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);

	std::wstring strValueOfBinDir;
	windowsRegistryTools.GetStringRegKey(hKey, L"Path", strValueOfBinDir, L"bad");

	if (bExistsAndSuccess)
	{
		std::string strInstallPath(OTString::ws2s(strValueOfBinDir));
		out_InstallFolderPath.Set(strInstallPath.c_str());

		return true;
	}

	
	return false;
}
Пример #4
0
// static
// Changes ~/blah to /Users/au/blah
//
void OTLog::TransformFilePath(const char * szInput, OTString & strOutput)
{
    if (NULL == szInput)
        return;
    
#ifndef _WIN32 // if UNIX (NOT windows)
	wordexp_t exp_result;
	wordexp(szInput, &exp_result, 0);
	
	strOutput.Set(exp_result.we_wordv[0]);
    
	wordfree(&exp_result); 
#else
	strOutput.Set(szInput);
#endif  
}
Пример #5
0
// ***********************************************************************
//
// INI FILE
//
bool GetOTAppDataFolderLocation(OTString strIniFileDefault, OTString & strOTServerDataLocation)
{
    CSimpleIniA ini;
    SI_Error rc = ini.LoadFile(strIniFileDefault.Get());
    if (rc >=0)
    {
        {
            const char * pVal = ini.GetValue("paths", "server_path", SERVER_PATH_DEFAULT); // todo stop hardcoding.
            
            if (NULL != pVal)
            {
                strOTServerDataLocation.Set(pVal);
                OTLog::vOutput(0, "Reading ini file (%s). \n Found Server data_folder path: %s \n", 
                               strIniFileDefault.Get(), strOTServerDataLocation.Get());
                return true;
            }
            
            OTLog::vOutput(0, "Reading ini file (%s) \n", strIniFileDefault.Get());
            return false;
        }            
    }
    else 
    {
        OTLog::vOutput(0, "Unable to load ini file (%s) to find data_folder path \n", 
                       strIniFileDefault.Get());
        return false;
    }
}
Пример #6
0
// ---------------------------------------
bool MTRecord::FormatShortMailDescription(std::string & str_output)
{
    OTString strDescription;

    if (IsMail())
    {
        if (!HasContents())
            strDescription.Set("(empty message)");
        else
        {
            std::string str_contents = GetContents();

            if (str_contents.compare(0,8,"Subject:") == 0)
            {
                // Make the replacement.
                str_contents.replace(0, 8, "");
            }
            // -----------------------------------
            bool bTruncated = false;

            if (str_contents.size() > 30)
            {
                str_contents.erase(30, std::string::npos);
                bTruncated = true;
            }
            // -----------------------------------
            strDescription.Format("\"%s%s\"", OTString::trim(str_contents).c_str(),
                                  bTruncated ? "..." : "");
        }
    }
    // -----------------------------
    str_output = strDescription.Get();
    // -----------------------------
    return (!str_output.empty());
}
Пример #7
0
void OTString::Truncate(uint32_t lAt)
{
    OTString strTruncated;

    strTruncated.Set(this->Get(), lAt);

    this->Set(strTruncated);
}
Пример #8
0
/// if we pack, compress, encode on the way in, that means, therefore, we
/// need to decode, uncompress, then unpack on our way out. Right?
///
/// This function will base64-DECODE the string contents, then uncompress them using
/// zlib, and then unpack the result using whatever is the default packer (MsgPack, Protobuf, etc).
/// 
/// I originally added compression because message sizes were too big. Now I'm adding packing, 
/// to solve any issues of binary compatibility across various platforms.
//
bool OTASCIIArmor::GetAndUnpackString(OTString & strData, bool bLineBreaks) const //bLineBreaks=true
{	
	size_t		outSize	= 0;
	uint8_t *	pData	= NULL;
	
	strData.Release();
	
	if (GetLength() < 1)
	{
		return true;
	}
	// --------------------------------------------------------------
	pData = OTCrypto::It()->Base64Decode(this->Get(), &outSize, bLineBreaks);
//	pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0));
	
	if (pData)
	{
        
        std::string str_decoded( pData, pData+outSize );
        
        delete [] pData; pData=NULL;

        std::string str_uncompressed = decompress_string( str_decoded );
		// ---------------------------------------
		// PUT THE PACKED BUFFER HERE, AND UNPACK INTO strData
		// --------------------------------------------------------
		OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either.
		
		OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up.
		OT_ASSERT(NULL != pBuffer);
		OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // This will make sure buffer is deleted later.
		      
        pBuffer->SetData(reinterpret_cast<const uint8_t *>(str_uncompressed.data()), str_uncompressed.size());
		// -----------------------------
		OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING));
		OT_ASSERT(NULL != pOTDBString);
		OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // clean up this string.
		
		bool bUnpacked = pPacker->Unpack(*pBuffer, *pOTDBString);
		// ----------------------
		if (false == bUnpacked)
		{
			OTLog::Error("Failed unpacking string in OTASCIIArmor::GetAndUnpackString.\n");
			
			return false;
		}
		// --------------------------------------------------------
		// This enforces the null termination. (using the 2nd parameter as nEnforcedMaxLength)
		strData.Set(pOTDBString->m_string.c_str(), static_cast<uint32_t> (pOTDBString->m_string.length()));
		
		return true;
	}
	else 
	{
		OTLog::Error("OTASCIIArmor::GetAndUnpackString: NULL pData while base64-decoding pData.\n");
		return false;
	}
}
Пример #9
0
const bool GetExecutable(OTString & strExecutablePath)
{
#ifdef TARGET_OS_MAC
	char bufPath[PATH_MAX + 1]="";
	uint32_t size = sizeof(bufPath);
	int  bufsize = sizeof(bufPath);
	if (_NSGetExecutablePath(bufPath, &size) == 0)
		strExecutablePath.Set(bufPath);
	else return false;
#elif defined __linux__

	char buff[4096]="";
	ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
	if (len != -1) {  // good
		buff[len] = '\0';
		strExecutablePath.Set(buff);
	}
	else {  // bad
		strExecutablePath.Set("");
		return false;
	}

#elif defined _WIN32

#ifdef _UNICODE
	TCHAR bufPath[ _MAX_PATH+1 ] = L"";
#else
	TCHAR bufPath[ _MAX_PATH+1 ] = "";
#endif

	GetModuleFileName( NULL , bufPath , sizeof(bufPath)/sizeof(TCHAR) ) ;

#ifdef UNICODE
	strExecutablePath.Set(utf8util::UTF8FromUTF16(bufPath));
#else
	strExecutablePath.Set(bufPath);
#endif
#else
	return false;
#endif
	return true;
}
Пример #10
0
const bool OTPaths::FixPath(const OTString & strPath, OTString & out_strFixedPath, const bool & bIsFolder)
{
	if (!strPath.Exists())			{ OTLog::sError("%s: Null: %s passed in!\n", __FUNCTION__, "strPath"	); OT_ASSERT(false); }



	std::string l_strPath(strPath.Get());
	// first change all back-slashes to forward slashes:
	std::string l_strPath_noBackslash(OTString::replace_chars(l_strPath,"\\",'/'));


	// now we make sure we have the correct trailing "/".

	if ('/' == *l_strPath_noBackslash.rbegin())
	{
		if (bIsFolder)
		{
			out_strFixedPath.Set(l_strPath_noBackslash.c_str());
			return true;
		}
		else
		{
			out_strFixedPath.Set(l_strPath_noBackslash.substr(0, l_strPath_noBackslash.size()-1).c_str());
			return true;
		}
	}
	else
	{
		if (bIsFolder)
		{
			l_strPath_noBackslash += "/";
			out_strFixedPath.Set(l_strPath_noBackslash.c_str());
			return true;
		}
		else
		{
			out_strFixedPath.Set(l_strPath_noBackslash.c_str());
			return true;
		}
	}
}
Пример #11
0
// This code reads up the file, discards the bookends, and saves only the gibberish itself.
bool OTASCIIArmor::LoadFrom_ifstream(std::ifstream & fin)
{
	std::stringstream buffer;
	buffer << fin.rdbuf();
	
	std::string contents(buffer.str());
	
	OTString theString;
	theString.Set(contents.c_str());
	
	return LoadFromString(theString);
}
Пример #12
0
// static
// Changes ~/blah to /Users/au/blah
//
void OTLog::TransformFilePath(const char * szInput, OTString & strOutput)
{
    OT_ASSERT(NULL != szInput);
     	
#ifndef _WIN32 // if UNIX (NOT windows)
	wordexp_t exp_result;
	
	if (wordexp(szInput, &exp_result, 0))
	{
		OTLog::Error("OTLog::TransformFilePath: Error calling wordexp() to expand path.\n");
		wordfree(&exp_result); 
		strOutput.Set(szInput);
		return;
	}
	// ----------------------------
	
	std::string str_Output("");
	
	// wordexp tokenizes by space (as well as expands, which is why I'm using it.)
	// Therefore we need to iterate through the tokens, and create a single string
	// with spaces between the tokens.
	//
	for (int i = 0; exp_result.we_wordv[i] != NULL; i++)
	{
		str_Output += exp_result.we_wordv[i];
		
		if (exp_result.we_wordv[i+1] != NULL)
			str_Output += " ";
	}
	
	wordfree(&exp_result); 

    if (str_Output.size() > 0)
        strOutput.Set(str_Output.c_str());
    else
        strOutput.Set(szInput);
#else
	strOutput.Set(szInput);
#endif  
}
// ***********************************************************************
//
// INI FILE
//
bool GetOTAppDataFolderLocation(const OTString & strIniFileDefault, OTString & strOTServerDataLocation)
{
    CSimpleIniA ini;
    SI_Error rc = ini.LoadFile(strIniFileDefault.Get());
    if (rc >=0)
    {
        {
            const char * pVal = ini.GetValue("paths", "prefix_path", OT_PREFIX_DEFAULT); // todo stop hardcoding.
            
            if (NULL != pVal)
            {
                OTLog::SetPrefixPath(pVal);
                OTLog::vOutput(0, "server main: Reading ini file (%s). \n Found prefix_path: %s \n", 
                               strIniFileDefault.Get(), OTLog::PrefixPath());
            }
            else
                OTLog::vOutput(0, "server main:Ini file: %s: Failed to find prefix_path. \n", strIniFileDefault.Get());
        }            
        {
            const char * pVal = ini.GetValue("paths", "init_path", OT_FOLDER_DEFAULT); // todo stop hardcoding.
            
            if (NULL != pVal)
            {
                OTLog::SetConfigPath(pVal);
                OTLog::vOutput(0, "server main: Reading ini file (%s). \n Found Server init_path: %s \n", 
                               strIniFileDefault.Get(), OTLog::ConfigPath());
            }
            else
                OTLog::vOutput(0, "server main:Ini file: %s: Failed to find init_path. \n", strIniFileDefault.Get());
        }            
        {
            const char * pVal = ini.GetValue("paths", "server_path", SERVER_PATH_DEFAULT); // todo stop hardcoding.
            
            if (NULL != pVal)
            {
                strOTServerDataLocation.Set(pVal);
                OTLog::vOutput(0, "server main: Reading ini file (%s). \n Found Server data_folder path: %s \n", 
                               strIniFileDefault.Get(), strOTServerDataLocation.Get());
                return true;
            }
            
            OTLog::vOutput(0, "server main: Reading ini file (%s) \n", strIniFileDefault.Get());
            return false;
        }            
    }
    else 
    {
        OTLog::vOutput(0, "server main: Unable to load ini file (%s) to find data_folder path \n", 
                       strIniFileDefault.Get());
        return false;
    }
}
Пример #14
0
const bool OTPaths::GetHomeFromSystem(OTString & out_strHomeFolder)
{
#ifdef _WIN32
#ifdef _UNICODE
	TCHAR szPath[MAX_PATH]=L"";
#else
	TCHAR szPath[MAX_PATH]="";
#endif

	if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) {
#ifdef UNICODE
		out_strHomeFolder.Set(utf8util::UTF8FromUTF16(szPath));
#else
		out_strHomeFolder.Set(szPath);
#endif
	}
	else { out_strHomeFolder.Set(""); return false; }
#else
	out_strHomeFolder.Set(getenv("HOME"));
#endif
	return true;
}
Пример #15
0
const bool GetCurrentWorking(OTString & strCurrentWorkingPath)
{

#ifdef _WIN32
	// Windows Common
	TCHAR * szPath = NULL;
#ifdef _UNICODE
	// Windows Unicode
#define GetCurrentDir _wgetcwd
#else
	// Windows No-Unicode
#define GetCurrentDir _getcwd
#endif
#else
	// Unix
#define GetCurrentDir getcwd
	char * szPath = NULL;
#endif

	// All
	bool r = ((szPath = GetCurrentDir(NULL,0)) == 0);
	OT_ASSERT(0 != r);

	OTString result;

#ifdef _WIN32
#ifdef _UNICODE
	// Windows Unicode
	strCurrentWorkingPath.Set(utf8util::UTF8FromUTF16(szPath));
#endif
#else
	// Unix
	strCurrentWorkingPath.Set(szPath);
#endif
	// All
	return true;
}
Пример #16
0
// ---------------------------------------
bool MTRecord::FormatShortMailDescription(std::string & str_output)
{
    OTString strDescription;

    if (IsMail())
    {
        if (!HasContents())
            strDescription.Set("(empty message)");
        else
        {
            std::string str_temp_contents = GetContents();
            std::string str_contents      = OTString::trim(str_temp_contents);

            if (str_contents.compare(0,8,"Subject:") == 0)
            {
                // Make the replacement.
                str_contents.replace(0, 8, "");
            }
            // -----------------------------------
            bool bTruncated = false;

            if (str_contents.size() > 30)
            {
                str_contents.erase(30, std::string::npos);
                bTruncated = true;
            }
            // -----------------------------------
            // Replace any newlines with spaces...
            //
            std::replace( str_contents.begin(), str_contents.end(), '\r', ' ');
            std::replace( str_contents.begin(), str_contents.end(), '\n', ' ');

//          str_contents.erase(std::remove(str_contents.begin(), str_contents.end(), '\n'), str_contents.end());
//          str_contents.erase(std::remove(str_contents.begin(), str_contents.end(), '\r'), str_contents.end());
            // -----------------------------------
            strDescription.Format("%s%s", OTString::trim(str_contents).c_str(),
                                  bTruncated ? "..." : "");
        }
    }
    // -----------------------------
    str_output = strDescription.Get();
    // -----------------------------
    return (!str_output.empty());
}
Пример #17
0
	// The Trade always stores the original, signed version of its Offer.
	// This method allows you to grab a copy of it.
	inline bool GetOfferString(OTString & strOffer)
	{ strOffer.Set(m_strOffer); return m_strOffer.Exists() ? true : false; }
// Lucre step 3: the mint signs the token
// 
bool OTMint_Lucre::SignToken(OTPseudonym & theNotary, OTToken & theToken, OTString & theOutput, int32_t nTokenIndex)
{
	bool bReturnValue = false;
	
	//OTLog::Error("%s <bank file> <coin request> <coin signature> [<signature repeats>]\n",
    _OT_Lucre_Dumper setDumper;
	
//	OTLog::vError("OTMint::SignToken!!\nnTokenIndex: %d\n Denomination: %lld\n", nTokenIndex, theToken.GetDenomination());
	
    OpenSSL_BIO bioBank		= BIO_new(BIO_s_mem()); // input
    OpenSSL_BIO bioRequest		= BIO_new(BIO_s_mem()); // input
    OpenSSL_BIO bioSignature	= BIO_new(BIO_s_mem()); // output
	
	OTASCIIArmor thePrivate;
	GetPrivate(thePrivate, theToken.GetDenomination());
	
	// The Mint private info is encrypted in m_mapPrivates[theToken.GetDenomination()]. 
	// So I need to extract that first before I can use it.
	OTEnvelope theEnvelope(thePrivate);

	OTString strContents; // output from opening the envelope.
	// Decrypt the Envelope into strContents    
	if (!theEnvelope.Open(theNotary, strContents))
		return false;

	// copy strContents to a BIO
	BIO_puts(bioBank, strContents.Get());
	
//	OTLog::vError("BANK CONTENTS:\n%s--------------------------------------\n", strContents.Get());
	
	// Instantiate the Bank with its private key
    Bank bank(bioBank);
//	OTLog::vError("BANK INSTANTIATED.--------------------------------------\n");

	// I need the request. the prototoken.
	OTASCIIArmor ascPrototoken;
	bool bFoundToken = theToken.GetPrototoken(ascPrototoken, nTokenIndex);
	
	if (bFoundToken)
	{
		// base64-Decode the prototoken
		OTString strPrototoken(ascPrototoken);
		
//		OTLog::vError("\n--------------------------------------\nDEBUG:  PROTOTOKEN CONTENTS:\n"
//				"-----------------%s---------------------\n", strPrototoken.Get() );
		
		// copy strPrototoken to a BIO
		BIO_puts(bioRequest, strPrototoken.Get());

		// Load up the coin request from the bio (the prototoken)
		PublicCoinRequest req(bioRequest);
//		OTLog::Error("PROTOTOKEN INSTANTIATED.--------------------------------------\n");

		// Sign it with the bank we previously instantiated.
		// results will be in bnSignature (BIGNUM)
		BIGNUM * bnSignature = bank.SignRequest(req);

		if (NULL == bnSignature)
		{
			OTLog::Error("MAJOR ERROR!: Bank.SignRequest failed in OTMint_Lucre::SignToken\n");
		}
		
		else 
		{
//			OTLog::Error("BANK.SIGNREQUEST SUCCESSFUL.--------------------------------------\n");

			// Write the request contents, followed by the signature contents,
			// to the Signature bio. Then free the BIGNUM.
			req.WriteBIO(bioSignature); // the original request contents
			DumpNumber(bioSignature,"signature=", bnSignature); // the new signature contents
			BN_free(bnSignature);

			// Read the signature bio into a C-style buffer...
			char sig_buf[1024];   // todo stop hardcoding these string lengths
//			memset(sig_buf, 0, 1024); // zero it out. (I had this commented out, but the size was 2048, so maybe it's safe now at 1024.)
			
			int32_t sig_len	= BIO_read(bioSignature, sig_buf, 1000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
			
			
			// Add the null terminator by hand (just in case.)
			sig_buf[sig_len]	= '\0';
			
			if (sig_len)
			{ // ***********************************************
//				OTLog::vError("\n--------------------------------------\n"
//						"*** Siglen is %d. sig_str_len is %d.\nsig buf:\n------------%s------------\nLAST "
//						"CHARACTER IS '%c'  SECOND TO LAST CHARACTER IS '%c'\n", 
//						sig_len, sig_str_len, sig_buf, sig_buf[sig_str_len-1], sig_buf[sig_str_len-2]);
				
				// Copy the original coin request into the spendable field of the token object.
				// (It won't actually be spendable until the client processes it, though.)
				theToken.SetSpendable(ascPrototoken);
				
//				OTLog::vError("*** SPENDABLE:\n-----------%s---------------------\n", ascPrototoken.Get());
						
						
				// Base64-encode the signature contents into theToken.m_Signature.
				OTString	strSignature(sig_buf);
	//			strSignature.Set(sig_buf, sig_len-1); // sig_len includes null terminator, whereas Set() adds 1 for it.
				
//				OTLog::vError("SIGNATURE:\n--------------------%s"
//						"------------------\n", strSignature.Get());

				// Here we pass the signature back to the caller.
				// He will probably set it onto the token.
				theOutput.Set(sig_buf, sig_len);
				bReturnValue = true;
				
				// This is also where we set the expiration date on the token.
				// The client should have already done this, but we are explicitly
				// setting the values here to prevent any funny business.
				theToken.SetSeriesAndExpiration(m_nSeries, m_VALID_FROM, m_VALID_TO);
			}
		}
	}

	return bReturnValue;
}
// The mint has a different key pair for each denomination.
// Pass the actual denomination such as 5, 10, 20, 50, 100...
bool OTMint_Lucre::AddDenomination(OTPseudonym & theNotary, int64_t lDenomination, int32_t nPrimeLength/*=1024*/)
{
    OT_ASSERT(NULL != m_pKeyPublic);
    
	bool bReturnValue = false;
	
	// Let's make sure it doesn't already exist
	OTASCIIArmor theArmor;
	if (GetPublic(theArmor, lDenomination))
	{
		// it already exists.
		OTLog::Error("Error: Denomination public already exists in OTMint::AddDenomination\n");
		return false;
	}
	if (GetPrivate(theArmor, lDenomination))
	{
		// it already exists.
		OTLog::Error("Error: Denomination private already exists in OTMint::AddDenomination\n");
		return false;
	}
	
	//		OTLog::Error("%s <size of bank prime in bits> <bank data file> <bank public data file>\n",
	
    if ((nPrimeLength/8) < (MIN_COIN_LENGTH+DIGEST_LENGTH))
	{
		OTLog::vError("Prime must be at least %d bits\n",
				(MIN_COIN_LENGTH+DIGEST_LENGTH)*8);
		return false;
	}
	
    if (nPrimeLength%8)
	{
		OTLog::Error("Prime length must be a multiple of 8\n");
		return false;
	}
	
#ifdef _WIN32
	SetMonitor("openssl.dump");
#else
	SetMonitor(stderr);
#endif
	
    OpenSSL_BIO bio		=	BIO_new(BIO_s_mem());
    OpenSSL_BIO bioPublic	=	BIO_new(BIO_s_mem());
	
	// Generate the mint private key information
    Bank bank(nPrimeLength/8);
    bank.WriteBIO(bio);
	
	// Generate the mint public key information
    PublicBank pbank(bank);
    pbank.WriteBIO(bioPublic);	
	
	// Copy from BIO back to a normal OTString or Ascii-Armor  
	char privateBankBuffer[4096], publicBankBuffer[4096];   // todo stop hardcoding these string lengths
	int32_t  privatebankLen	= BIO_read(bio, privateBankBuffer, 4000); // cutting it a little short on purpose, with the buffer.
	int32_t  publicbankLen	= BIO_read(bioPublic, publicBankBuffer, 4000); // Just makes me feel more comfortable for some reason.
	
	if (privatebankLen && publicbankLen)
	{
		// With this, we have the Lucre public and private bank info converted to OTStrings
		OTString strPublicBank;		strPublicBank.Set(publicBankBuffer, publicbankLen);
		OTString strPrivateBank;	strPrivateBank.Set(privateBankBuffer, privatebankLen);
		
		OTASCIIArmor * pPublic	= new OTASCIIArmor();
		OTASCIIArmor * pPrivate	= new OTASCIIArmor();
		
		OT_ASSERT(NULL != pPublic);
		OT_ASSERT(NULL != pPrivate);
		
		// Set the public bank info onto pPublic
		pPublic->SetString(strPublicBank, true); // linebreaks = true
		
		// Seal the private bank info up into an encrypted Envelope 
		// and set it onto pPrivate
		OTEnvelope theEnvelope;
		theEnvelope.Seal(theNotary, strPrivateBank);	// Todo check the return values on these two functions
		theEnvelope.GetAsciiArmoredData(*pPrivate);
		
		// Add the new key pair to the maps, using denomination as the key
		m_mapPublic[lDenomination]	= pPublic;
		m_mapPrivate[lDenomination]	= pPrivate;
		
		// Grab the Server Nym ID and save it with this Mint
		theNotary.GetIdentifier(m_ServerNymID);
        // ---------------------------
		// Grab the Server's public key and save it with this Mint
        //
        const OTAsymmetricKey & theNotaryPubKey = theNotary.GetPublicSignKey();
        delete m_pKeyPublic;
        m_pKeyPublic = theNotaryPubKey.ClonePubKey();
        // ---------------------------
		m_nDenominationCount++;
        // ---------------------------		
		// Success!
		bReturnValue = true;
		OTLog::vOutput(1, "Successfully added denomination: %lld\n", lDenomination);
	}
	
	return bReturnValue;
}
Пример #20
0
// Lucre step 4: client unblinds token -- now it's ready for use.
bool OTToken::ProcessToken(const OTPseudonym & theNym, OTMint & theMint, OTToken & theRequest)
{
//		OTLog::vError("%s <bank public info> <private coin request> <signed coin request> <coin>\n",
	bool bReturnValue = false;
	
	// When the Mint has signed a token and sent it back to the client,
	// the client must unblind the token and set it as spendable. Thus,
	// this function is only performed on tokens in the signedToken state.
	if (OTToken::signedToken != m_State)
	{
		OTLog::Error("Signed token expected in OTToken::ProcessToken\n");
		return false;
	}
	
	// Lucre
    SetDumper(stderr);
    BIO *bioBank			= BIO_new(BIO_s_mem()); // input
    BIO *bioSignature		= BIO_new(BIO_s_mem()); // input
    BIO *bioPrivateRequest	= BIO_new(BIO_s_mem()); // input
    BIO *bioCoin			= BIO_new(BIO_s_mem()); // output
	
	// Get the bank's public key (decoded into strPublicMint)
	// and put it into bioBank so we can use it with Lucre.
	OTASCIIArmor ascPublicMint;
	theMint.GetPublic(ascPublicMint, GetDenomination());
	OTString strPublicMint(ascPublicMint);
	BIO_puts(bioBank, strPublicMint.Get());

	// Get the existing signature into a bio.
//	OTLog::vError("DEBUGGING, m_Signature: -------------%s--------------\n", m_Signature.Get());
	OTString strSignature(m_Signature);
	BIO_puts(bioSignature, strSignature.Get());
	
	// I need the Private coin request also. (Only the client has this private coin request data.)
	OTASCIIArmor thePrototoken;		// The server sets m_nChosenIndex when it signs the token.
	bool bFoundToken = theRequest.GetPrivatePrototoken(thePrototoken, m_nChosenIndex);
	
	if (bFoundToken)
	{
//		OTLog::vError("THE PRIVATE REQUEST ARMORED CONTENTS:\n------------------>%s<-----------------------\n",
//				thePrototoken.Get());
		
		// Decrypt the prototoken
		OTString strPrototoken;
		OTEnvelope theEnvelope(thePrototoken);
		theEnvelope.Open(theNym, strPrototoken); // todo check return value.
		
//		OTLog::vError("THE PRIVATE REQUEST CONTENTS:\n------------------>%s<-----------------------\n",
//				strPrototoken.Get());
		
		// copy strPrototoken to a BIO
		BIO_puts(bioPrivateRequest, strPrototoken.Get());
		
		// ------- Okay, the BIOs are all loaded.... let's process...
		
		PublicBank	bank(bioBank);
		CoinRequest	req(bioPrivateRequest);
		
		// TODO make sure I'm not leaking memory with these ReadNumbers
		// Probably need to be calling some free function for each one.
		
		// Apparently reading the request id here and then just discarding it...
		ReadNumber(bioSignature,"request=");
		
		// Versus the signature data, which is read into bnSignature apparently.
		BIGNUM * bnSignature	= ReadNumber(bioSignature,"signature=");
		DumpNumber("signature=", bnSignature);
		
		// Produce the final unblinded token in Coin coin, and write it to bioCoin...
		Coin coin; // Coin Request, processes into Coin, with Bank and Signature passed in.
		req.ProcessResponse(&coin, bank, bnSignature); // Notice still apparently "request" info is discarded.
		coin.WriteBIO(bioCoin);
		
		// convert bioCoin to a C-style string...
		char CoinBuffer[1024];   // todo stop hardcoding these string lengths
		int coinLen	= BIO_read(bioCoin, CoinBuffer, 1000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
		
		if (coinLen)
		{
			// ...to OTString...
			OTString strCoin;	
			strCoin.Set(CoinBuffer, coinLen);
			
//			OTLog::vError("Processing token...\n%s\n", strCoin.Get());
			
			// ...to Envelope stored in m_ascSpendable (encrypted and base64-encoded)
			OTEnvelope theEnvelope;
			theEnvelope.Seal(theNym, strCoin);	// Todo check the return values on these two functions
			theEnvelope.GetAsciiArmoredData(m_ascSpendable); // Here's the final product.
			
//			OTLog::vError("NEW SPENDABLE token...\n--------->%s<----------------\n", m_ascSpendable.Get());

			// Now the coin is encrypted from here on out, and otherwise ready-to-spend.
			m_State			= OTToken::spendableToken;
			bReturnValue	= true;
			
			// Lastly, we free the signature data, which is no longer needed, and which could be
			// otherwise used to trace the token. (Which we don't want.)
			m_Signature.Release();
		}
		
	}
	// Todo log error here if the private prototoken is not found. (Very strange if so!!)
	//  else {}
	
	// Cleanup openssl resources.
	BIO_free_all(bioBank);	
	BIO_free_all(bioSignature);	
	BIO_free_all(bioPrivateRequest);	
	BIO_free_all(bioCoin);	

	return bReturnValue;	
}
Пример #21
0
bool OTEnvelope::Open(const OTPseudonym & theRecipient, OTString & theContents)
{
	bool retval = false;
	
    EVP_CIPHER_CTX	ctx;

    unsigned char	buffer[4096];
    unsigned char	buffer_out[4096 + EVP_MAX_IV_LENGTH];
    unsigned char	iv[EVP_MAX_IV_LENGTH];

    size_t			len = 0;
    int				len_out = 0;
    
	unsigned char *	ek = NULL;
    int				eklen = 0;
    uint32_t		eklen_n = 0;
	
	memset(buffer, 0, 4096);
	memset(buffer_out, 0, 4096 + EVP_MAX_IV_LENGTH);
	memset(iv, 0, EVP_MAX_IV_LENGTH);

	OTAsymmetricKey &	privateKey	= (OTAsymmetricKey &)theRecipient.GetPrivateKey();
	EVP_PKEY *			pkey		= (EVP_PKEY *)privateKey.GetKey();
	
	if (NULL == pkey)
	{
		OTLog::Error("Null private key in OTEnvelope::Open\n");
		return false;
	}
		
	EVP_CIPHER_CTX_init(&ctx);
    ek = (unsigned char*)malloc(EVP_PKEY_size(pkey));  // I assume this is for the AES key
	
	OT_ASSERT(NULL != ek);
	
	memset(ek, 0, EVP_PKEY_size(pkey));

	eklen = EVP_PKEY_size(pkey);
	
	
	//int EVP_OpenInit(EVP_CIPHER_CTX *ctx,
	//EVP_CIPHER *type,
	//unsigned char *ek, 
	//int ekl,
	//unsigned char *iv,
	//EVP_PKEY *priv);
	
	//EVP_OpenInit() initializes a cipher context ctx for decryption with cipher type. It decrypts the encrypted 
	//	symmetric key of length ekl bytes passed in the ek parameter using the private key priv. The IV is supplied 
	//	in the iv parameter.
		

	theContents.Release();	// This is where we'll put the decrypted data.
	m_dataContents.reset(); // reset the fread position on this object.
	
	int nReadLength = 0;
	int nReadKey = 0;
	int nReadIV = 0;
	
	// First we read the encrypted key size.
	if (0 == (nReadLength = m_dataContents.OTfread((char*)&eklen_n, sizeof(eklen_n))))
	{
		OTLog::Error("Error reading encrypted key size in OTEnvelope::Open\n");
		free(ek); ek = NULL;
		return false;
	}
	
	// convert it from network to host endian.
	eklen = ntohl(eklen_n);
	
	// Next we read the encrypted key itself.
	if (0 == (nReadKey = m_dataContents.OTfread((char*)ek, eklen)))
	{
		OTLog::Error("Error reading encrypted key size in OTEnvelope::Open\n");
		free(ek); ek = NULL;
		return false;
	}
	
	// Next we read the initialization vector.
	if (0 == (nReadIV = m_dataContents.OTfread((char*)iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()))))
	{
		OTLog::Error("Error reading initialization vector in OTEnvelope::Open\n");
		free(ek); ek = NULL;
		return false;
	}
	
	OTData ciphertext((const void*)((unsigned char *)m_dataContents.GetPointer() + nReadLength + nReadKey + nReadIV), 
					  m_dataContents.GetSize() - nReadLength - nReadKey - nReadIV);
	
	
	
	// Now we process ciphertext and write the decrypted data to plaintext.
	OTData plaintext;

	if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv, pkey))
    {
        OTLog::Error("EVP_OpenInit: failed.\n");
		free(ek); ek = NULL;
		return false;
    }
		
    while ((len = ciphertext.OTfread((char*)buffer, sizeof(buffer))) > 0)
    {
        if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
        {
            OTLog::Error("EVP_OpenUpdate: failed.\n");
			free(ek); ek = NULL;
			return false;
        }
		
		OTData dataOpenUpdate(buffer_out, len_out);
		plaintext += dataOpenUpdate;
	}
	
    if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
    {
		OTLog::Error("EVP_OpenFinal: failed.\n");
 		free(ek); ek = NULL;
		return false;
    }
	
	OTData dataOpenFinal(buffer_out, len_out);
	plaintext += dataOpenFinal;
	
	// Make sure it's null terminated
	int nIndex = plaintext.GetSize()-1;
	((unsigned char*)plaintext.GetPointer())[nIndex] = 0;
	
	// Set it into theContents (to return the plaintext to the caller)
	theContents.Set((const char *)plaintext.GetPointer());
	
	retval = true;
	
    free(ek); ek = NULL;
	
    return retval;
	
}
Пример #22
0
const bool OTPaths::ToReal(const OTString & strExactPath, OTString & out_strCanonicalPath)
{
	if (!strExactPath.Exists())		{ OTLog::sError("%s: Null: %s passed in!\n", __FUNCTION__, "strExactPath"); OT_ASSERT(false); }

#ifdef _WIN32
#ifdef _UNICODE	

	const char * szPath = strExactPath.Get();
	size_t newsize = strlen(szPath) + 1;
	wchar_t * wzPath = new wchar_t[newsize];

	size_t convertedChars = 0;
	mbstowcs_s(&convertedChars, wzPath, newsize, szPath,4096);

	wchar_t szBuf[4096]= L"";

	if(GetFullPathName(wzPath,4096,szBuf,NULL))
	{
		out_strCanonicalPath.Set(utf8util::UTF8FromUTF16(szBuf));
		return true;
	}
	else 
	{
		out_strCanonicalPath.Set("");
		return false;
	}

#else
	char_t szBuf[4096]="";
	char_t const * szPath = strRealPath.Get();

	if(GetFullPathName(szPath,4096,szBuf,NULL))
	{
		out_strCanonicalPath.Set(szBuf);
		return true;
	}
	else
	{
		out_strCanonicalPath.Set("");
		return false;
	}

#endif
#else

	long path_max=0;
#ifdef PATH_MAX
	path_max = PATH_MAX;
#else
	path_max = pathconf("/", _PC_PATH_MAX);
	if (path_max <= 0)  path_max = 4096;
#endif

	char actualpath [path_max+1];
    actualpath[0] = '\0';
	char *ptr=NULL;

	if (NULL ==  realpath(strExactPath.Get(), actualpath)) {

		if (errno == ENOTDIR) {
			OTLog::vOutput(1,"Input value to RealPath is not a directory: (Realpath: skipping)\n");
			out_strCanonicalPath.Set(strExactPath);
			return true;
		}

		if (errno == ENOENT) {
			OTLog::vOutput(1,"File doesn't exist: (Realpath: skipping)\n");
			out_strCanonicalPath.Set(strExactPath);
			return true;
		}

		OT_ASSERT_MSG((errno != EACCES),"Error (Realpath: EACCES): Unable to build RealPath: access denied");
		OT_ASSERT_MSG((errno != EINVAL),"Error (RealPath: EINVAL): Input value into RealPath was NULL");
		OT_ASSERT_MSG((errno != ELOOP),"Error (RealPath: ELOOP): Resloving links resulted in a loop.");
		OT_ASSERT_MSG((errno != ENAMETOOLONG),"Error (RealPath: ENAMETOOLONG): Name too long.");
		OT_ASSERT_MSG((errno != ERANGE),"Error (RealPath: ERANGE): Resulting path is too long for the buffer");
		OT_ASSERT_MSG((errno != EIO),"Error (RealPath: EIO): Unable to access path.");

		OT_ASSERT_MSG((false),"Error (RealPath: OTHER): Something bad Happend with 'realpath'.");
	}
	out_strCanonicalPath.Set(actualpath);
	return true;
#endif
}
Пример #23
0
//static
std::string OTAssetContract::formatLongAmount(int64_t & lOriginalValue, int32_t nFactor/*=100*/, int32_t nPower/*=2*/, const char * szSymbol/*=""*/,
                                              const char * szSeparator/*=","*/, const char * szDecimalPoint/*="."*/)
{
    std::stringstream sss;
    OTString strRemainder;
    // --------------------------------------------------
    // If the original value is 0, we still want to format the
    // string properly for a 0 value. (And then return.)
    //
    if (0 == lOriginalValue)
    {
        sss << szSymbol << " "; // Currency symbol
        
        if (!(nFactor < 2))
        {
            sss << szDecimalPoint;
            
            strRemainder.Format("%0*ld", nPower, 0);
        }
        else
            strRemainder.Format("%lld", 0);
        
        sss << strRemainder.Get();
        return sss.str();
    }
    // --------------------------------------------------
    int64_t lAbsoluteValue = (lOriginalValue > 0) ? lOriginalValue : (lOriginalValue * (-1));
    // --------------------------------------------------    
    int64_t lValue     = lAbsoluteValue / nFactor; // For example, if 506 is supposed to be $5.06, then dividing 506 by factor of 100 results in 5 dollars.
    int64_t lRemainder = lAbsoluteValue % nFactor; // For example, if 506 is supposed to be $5.06, then 506 mod 100 results in 6 cents.
    
    if (nFactor < 2) // Basically, if nFactor is 1.
        strRemainder.Set("");
    else
        strRemainder.Format("%0*ld", nPower, lRemainder); // If remainder is 6 (cents) and nPower is 2, strRemainder gets set here to 06.    
    // ------------------------------------------------------
    // Here we add the negative sign, if the value itself is negative.
    //
    if (lOriginalValue < 0)
    {
//        const std::moneypunct<char, false> &mp = std::use_facet< std::moneypunct<char, false> >(std::locale ());
//        sss << mp.negative_sign();
     
        // For some reason the above code isn't working, so I've got the negative sign
        // hardcoded here to '-'.
        //
        sss << "-";
    }
    // ------------------------------------------------------    
    // Here we add the currency symbol.
    //
    sss << szSymbol << " "; // Currency symbol
    // ------------------------------------------------------
    OTString strValue;
    strValue.Format("%lld", lValue);
    // ---------------------------------
    char     cTemp = '\0';
    uint32_t uValueStrLength = strValue.GetLength();
    // ---------------------------------
    // Here we add the main body of the amount, including separators (commas.)
    //
    while (uValueStrLength > 0)
    {
        cTemp = strValue.sgetc();
        
        sss << cTemp;
        
        --uValueStrLength;
        
        if ((uValueStrLength > 0) && (0 == (uValueStrLength % 3)))
            sss << szSeparator;
    }
    // ------------------------------------------------------
    // Here we deal with the decimal point, etc.
    //
    if (!(nFactor < 2))
    {
        sss << szDecimalPoint;
        // -----------------------------
        sss << strRemainder.Get();
    }
    // -----------------------------
    return sss.str();
}
Пример #24
0
void OTToken::UpdateContents()
{
	if (m_State == OTToken::spendableToken)
		m_strContractType.Set("CASH");
	
	OTString ASSET_TYPE_ID(m_AssetTypeID), SERVER_ID(m_ServerID);
	
	OTString strState;
	switch (m_State) {
		case OTToken::blankToken:
			strState.Set("blankToken");
			break;
		case OTToken::protoToken:
			strState.Set("protoToken");
			break;
		case OTToken::signedToken:
			strState.Set("signedToken");
			break;
		case OTToken::spendableToken:
			strState.Set("spendableToken");
			break;
		case OTToken::verifiedToken:
			strState.Set("verifiedToken");
			break;
		default:
			strState.Set("errorToken");
			break;
	}

	long lFrom = m_VALID_FROM, lTo = m_VALID_TO;

	
	// I release this because I'm about to repopulate it.
	m_xmlUnsigned.Release();
	
	m_xmlUnsigned.Concatenate("<?xml version=\"%s\"?>\n\n", "1.0");		
	
	m_xmlUnsigned.Concatenate("<token\n version=\"%s\"\n state=\"%s\"\n denomination=\"%ld\"\n"
							  " assetTypeID=\"%s\"\n"
							  " serverID=\"%s\"\n"
							  " series=\"%d\"\n"
							  " validFrom=\"%ld\"\n"
							  " validTo=\"%ld\""							  
							  " >\n\n", 
							  m_strVersion.Get(), strState.Get(), GetDenomination(), 
							  ASSET_TYPE_ID.Get(), 
							  SERVER_ID.Get(),
							  m_nSeries, lFrom, lTo );		

	// signed tokens, as well as spendable tokens, both carry a TokenID
	// (The spendable token contains the unblinded version.)
	if (OTToken::signedToken	== m_State || 
		OTToken::spendableToken	== m_State)
	{
		m_xmlUnsigned.Concatenate("<tokenID>\n%s</tokenID>\n\n", m_ascSpendable.Get());
	}
	
	// Only signedTokens carry the signature, which is discarded in spendable tokens.
	// (Because it is not used past the unblinding stage anyway, and because it could
	// be used to track the token.)
	if (OTToken::signedToken == m_State)
	{
		m_xmlUnsigned.Concatenate("<tokenSignature>\n%s</tokenSignature>\n\n", m_Signature.Get());
	}
	
	if ((OTToken::protoToken == m_State || 
		 OTToken::signedToken == m_State)	&& m_nTokenCount)
	{
		m_xmlUnsigned.Concatenate("<protopurse count=\"%d\" chosenIndex=\"%d\">\n\n", m_nTokenCount, m_nChosenIndex);
		
		OTASCIIArmor * pPrototoken = NULL;
		for (mapOfPrototokens::iterator ii = m_mapPublic.begin(); ii != m_mapPublic.end(); ++ii)
		{
			pPrototoken = (*ii).second;
			
			OT_ASSERT(NULL != pPrototoken);
			
			m_xmlUnsigned.Concatenate("<prototoken>\n%s</prototoken>\n\n", pPrototoken->Get());
		}		
		m_xmlUnsigned.Concatenate("</protopurse>\n\n");
	}
	
	if (m_bSavePrivateKeys)
	{
		m_bSavePrivateKeys = false; // set it back to false;
		
		m_xmlUnsigned.Concatenate("<privateProtopurse>\n\n");
		
		OTASCIIArmor * pPrototoken = NULL;
		for (mapOfPrototokens::iterator ii = m_mapPrivate.begin(); ii != m_mapPrivate.end(); ++ii)
		{
			pPrototoken = (*ii).second;
			
			OT_ASSERT(NULL != pPrototoken);
			
			m_xmlUnsigned.Concatenate("<privatePrototoken>\n%s</privatePrototoken>\n\n", pPrototoken->Get());
		}		
		m_xmlUnsigned.Concatenate("</privateProtopurse>\n\n");
	}
	
	m_xmlUnsigned.Concatenate("</token>\n");			
}
bool OTASCIIArmor::GetString(OTString & theData, bool bLineBreaks) const //bLineBreaks=true
{	
	return GetAndUnpackString(theData, bLineBreaks);
	
	
	
	
	
	size_t		outSize	= 0;
	uint8_t *	pData	= NULL;
	
	theData.Release();
	
	if (GetLength() < 1) {
		return true;
	}
	
	pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0));
	
	if (pData)
	{
		long nDestLen = DEFAULT_BUFFER_SIZE_EASYZLIB; // todo stop hardcoding numbers (but this one is OK I think.)
		unsigned char* pDest = new unsigned char [nDestLen+10]; // For safety.
		
		OT_ASSERT(NULL != pDest);
		
		int nErr = ezuncompress( pDest, &nDestLen, pData, outSize );
		if ( nErr == EZ_BUF_ERROR )
		{
			delete [] pDest;
			pDest = new unsigned char [nDestLen]; // enough room now
			
			OT_ASSERT(NULL != pDest);
			
			nErr = ezuncompress( pDest, &nDestLen, pData, outSize );
		}
		
		// Now we're done with this memory, let's free it.
		delete [] pData; pData=NULL;
		
		// ----------------------------------------
		
		if ( nErr == EZ_BUF_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OT_ASSERT_MSG(false, "Buffer error in OTASCIIArmor::GetString\n");
			return false; // not really necessary but just making sure.
		}
		else if ( nErr == EZ_STREAM_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OT_ASSERT_MSG(false, "pDest is NULL in OTASCIIArmor::GetString\n");
			return false; // not really necessary but just making sure.
		}
		else if ( nErr == EZ_DATA_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OTLog::vError("corrupted pSrc passed to ezuncompress OTASCIIArmor::GetString, size: %d\n", outSize);
			
			OT_ASSERT(false);
			
			return false; // not really necessary but just making sure.
		}
		else if ( nErr == EZ_MEM_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OT_ASSERT_MSG(false, "Out of memory in OTASCIIArmor::GetString\n");
			return false; // not really necessary but just making sure.
		}
		
		// This enforces the null termination. (using the extra parameter nDestLen as nEnforcedMaxLength)
		theData.Set((const char*)pDest, nDestLen);
		
		delete [] pDest; pDest=NULL; 
		return true;
	}
	else 
	{
		OTLog::Error("NULL pData while base64_decodeing pData.\n");
		return false;
	}
}
Пример #26
0
// Lucre step 2 (client generates coin request)
// nDenomination must be one of the denominations supported by the mint.
// sets m_nTokenCount and populates the maps with prototokens (in ASCII-armored format.)
bool OTToken::GenerateTokenRequest(const OTPseudonym & theNym, OTMint & theMint, 
								   long lDenomination, int nTokenCount/*=OTToken::nMinimumPrototokenCount*/)
{		
	//	OTLog::vError("%s <bank public info> <coin request private output file> <coin request public output file>\n", argv[0]);

	if (OTToken::blankToken != m_State)
	{
		OTLog::Error("Blank token expected in OTToken::GenerateTokenRequest\n");
		return false;
	}
	
	// We are supposed to set these values here.
	// The server actually sets them again, for security reasons.
	// But we should still set them since server may choose to reject the request.
	SetSeriesAndExpiration(theMint.GetSeries(), theMint.GetValidFrom(), theMint.GetValidTo());
	
    SetDumper(stderr);
	
    BIO *bioBank		=	BIO_new(BIO_s_mem()); // Input. We must supply the bank's public lucre info
    BIO *bioCoin		=	BIO_new(BIO_s_mem()); // These two are output. We must write these bios, after
    BIO *bioPublicCoin	=	BIO_new(BIO_s_mem()); // the operation, back into some form we can use
	
	// This version base64-DECODES the ascii-armored string passed in,
	// and then sets the decoded plaintext string onto the string.
	//OTString::OTString(const OTASCIIArmor & strValue)
	OTASCIIArmor ascPublicMint;
	
	theMint.GetPublic(ascPublicMint, lDenomination);
	
//	OTLog::vError("DEBUG: OTToken  public asc: \n%s\n", ascPublicMint.Get());

	
	OTString strPublicMint(ascPublicMint);

//	OTLog::vError("DEBUG: OTToken  public str: \n%s\n", strPublicMint.Get());
	

	// Get the bank's public key (now decoded in strPublicMint)
	// and put it into bioBank so we can use it with Lucre.
	BIO_puts(bioBank, strPublicMint.Get());
	
	// Instantiate a PublicBank (Lucre) object.
	// We will use it to generate all the prototokens in the loop below.
    PublicBank bank;
    bank.ReadBIO(bioBank);
	
	Release();

	const int nFinalTokenCount = (nTokenCount < OTToken::nMinimumPrototokenCount) ? 
					OTToken::nMinimumPrototokenCount : nTokenCount; 
	
	// Token count is actually 1 (always) with Lucre, although this lib has potential to work with 
	// multiple proto-tokens, you can see this loop as though it always executes just once.
	for (int i = 0; i < nFinalTokenCount; i++)
	{
		CoinRequest req(bank);

		// write the private coin request to BIO
		req.WriteBIO(bioCoin);
		
		// write the public coin request to BIO
		((PublicCoinRequest *)&req)->WriteBIO(bioPublicCoin);
		
		// Convert the two bios to our format
		char privateCoinBuffer[4096], publicCoinBuffer[4096];   // todo stop hardcoding these string lengths
		int privatecoinLen	= BIO_read(bioCoin, privateCoinBuffer, 4000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
		int publiccoinLen	= BIO_read(bioPublicCoin, publicCoinBuffer, 4000); 
		
		if (privatecoinLen && publiccoinLen)
		{
			// With this, we have the Lucre public and private bank info converted to OTStrings
			OTString strPublicCoin;		strPublicCoin.Set(publicCoinBuffer, publiccoinLen);
			OTString strPrivateCoin;	strPrivateCoin.Set(privateCoinBuffer, privatecoinLen);
			
			OTASCIIArmor * pArmoredPublic	= new OTASCIIArmor(strPublicCoin);
			OTASCIIArmor * pArmoredPrivate	= new OTASCIIArmor();
			
			OT_ASSERT_MSG(((NULL != pArmoredPublic) && (NULL != pArmoredPrivate)), "ERROR: Unable to allocate memory in OTToken::GenerateTokenRequest\n");
			
			// Change the state. It's no longer a blank token, but a prototoken.
			m_State = OTToken::protoToken;

			// Seal the private coin info up into an encrypted Envelope 
			// and set it onto pArmoredPrivate (which was just added to our internal map, above.)
			OTEnvelope theEnvelope;
			theEnvelope.Seal(theNym, strPrivateCoin);	// Todo check the return values on these two functions
			theEnvelope.GetAsciiArmoredData(*pArmoredPrivate);
			
			m_mapPublic[i]	= pArmoredPublic;
			m_mapPrivate[i]	= pArmoredPrivate;

			m_nTokenCount = nFinalTokenCount;
			SetDenomination(lDenomination);
		}
		else {
			// Error condition
		}

		// Free the Private and Public coins and allocate them fresh, for the next iteration of the loop.
		BIO_free_all(bioCoin);	
		BIO_free_all(bioPublicCoin);

		bioCoin			=	BIO_new(BIO_s_mem());
		bioPublicCoin	=	BIO_new(BIO_s_mem());
	}
	
	
	// Cleanup openssl resources.
	BIO_free_all(bioBank);	
    BIO_free_all(bioCoin);	
    BIO_free_all(bioPublicCoin);
	
	return true;
}
Пример #27
0
/// if we pack, compress, encode on the way in, that means, therefore, we
/// need to decode, uncompress, then unpack on our way out. Right?
///
/// This function will base64-DECODE the string contents, then uncompress them using
/// zlib, and then unpack the result using whatever is the default packer (MsgPack, Protobuf, etc).
/// 
/// I originally added compression because message sizes were too big. Now I'm adding packing, 
/// to solve any issues of binary compatibility across various platforms.
//
bool OTASCIIArmor::GetAndUnpackString(OTString & strData, bool bLineBreaks) const //bLineBreaks=true
{	
	size_t		outSize	= 0;
	uint8_t *	pData	= NULL;
	
	strData.Release();
	
	if (GetLength() < 1)
	{
		return true;
	}
	// --------------------------------------------------------------
	pData = OTCrypto::It()->Base64Decode(this->Get(), &outSize, bLineBreaks);
//	pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0));
	
	if (pData)
	{
		// -------------------------------------------
		// EASY ZLIB
		//
		long nDestLen = DEFAULT_BUFFER_SIZE_EASYZLIB; // todo stop hardcoding numbers (but this one is OK I think.)
		unsigned char* pDest = new unsigned char [nDestLen+10]; // For safety.
		
		OT_ASSERT(NULL != pDest);
		
		int nErr = ezuncompress( pDest, &nDestLen, pData, static_cast<long> (outSize) );
		if ( nErr == EZ_BUF_ERROR )
		{
			delete [] pDest;
			pDest = new unsigned char [nDestLen]; // enough room now
			
			OT_ASSERT(NULL != pDest);
			
			nErr = ezuncompress( pDest, &nDestLen, pData, static_cast<long> (outSize) );
		}
		
		// Now we're done with this memory, let's free it.
		delete [] pData; pData=NULL;
		// ----------------------------------------
		if ( nErr == EZ_BUF_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OT_FAIL_MSG("Buffer error in OTASCIIArmor::GetAndUnpackString\n");
		}
		else if ( nErr == EZ_STREAM_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OT_FAIL_MSG("pDest is NULL in OTASCIIArmor::GetAndUnpackString\n");
		}
		else if ( nErr == EZ_DATA_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OTLog::vError("corrupted pSrc passed to ezuncompress OTASCIIArmor::GetAndUnpackString, size: %d\n", outSize);
			OT_FAIL;
		}
		else if ( nErr == EZ_MEM_ERROR )
		{
			delete [] pDest;
			pDest = NULL;
			
			OT_FAIL_MSG("Out of memory in OTASCIIArmor::GetAndUnpackString\n");
		}
		// ---------------------------------------
		// PUT THE PACKED BUFFER HERE, AND UNPACK INTO strData
		// --------------------------------------------------------
		OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either.
		
		OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up.
		OT_ASSERT(NULL != pBuffer);
		OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // This will make sure buffer is deleted later.
		
		const size_t theDestLen = nDestLen;
		
		pBuffer->SetData(pDest, // const unsigned char *
						 theDestLen);

		delete [] pDest; pDest=NULL; 
		// -----------------------------
		OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING));
		OT_ASSERT(NULL != pOTDBString);
		OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // clean up this string.
		
		bool bUnpacked = pPacker->Unpack(*pBuffer, *pOTDBString);
		// ----------------------
		if (false == bUnpacked)
		{
			OTLog::Error("Failed unpacking string in OTASCIIArmor::GetAndUnpackString.\n");
			
			return false;
		}
		// --------------------------------------------------------
		// This enforces the null termination. (using the 2nd parameter as nEnforcedMaxLength)
		strData.Set(pOTDBString->m_string.c_str(), static_cast<uint32_t> (pOTDBString->m_string.length()));
		
		return true;
	}
	else 
	{
		OTLog::Error("OTASCIIArmor::GetAndUnpackString: NULL pData while base64-decoding pData.\n");
		return false;
	}
}
Пример #28
0
int main (int argc, char **argv) 
{
	OTLog::vOutput(0, "\n\nWelcome to Open Transactions... Test Client -- version %s\n"
				   "(transport build: OTMessage -> TCP -> SSL)\n"
				   "IF YOU PREFER TO USE ZMQ (message based), then rebuild from main folder like this:\n"
				   "cd ..; make clean; make\n\n", 
				   OTLog::Version());

	OT_API::InitOTAPI();

	// -----------------------------------------------------------------------
	// The beginnings of an INI file!!

	OTString strPath;

	{
		CSimpleIniA ini; // We're assuming this file is on the path.
		SI_Error rc = ini.LoadFile("./.ot_ini"); // todo: stop hardcoding. 

		if (rc >=0)
		{
			const char * pVal = ini.GetValue("paths", "client_path", SERVER_PATH_DEFAULT); // todo stop hardcoding.

			if (NULL != pVal)
				strPath.Set(pVal);
			else
				strPath.Set(SERVER_PATH_DEFAULT);
		}
		else 
		{
			strPath.Set(SERVER_PATH_DEFAULT);
		}
	}
	// -----------------------------------------------------------------------

	OTString strCAFile, strKeyFile, strSSLPassword;

	if (argc < 2)
	{
		OTLog::vOutput(0, "\n==> USAGE:    %s   <SSL-password>  <absolute_path_to_data_folder>\n\n"
#if defined (FELLOW_TRAVELER)					   
				"(Password defaults to '%s' if left blank.)\n"
				"(Folder defaults to '%s' if left blank.)\n"
#else
				"(The test password is always 'test'.\n'cd data_folder' then 'pwd' to see the absolute path.)\n"
#endif
					   "\n\n", argv[0]
#if defined (FELLOW_TRAVELER)					   
					   , KEY_PASSWORD, 
					   strPath.Get()
#endif					   
					   );
	
#if defined (FELLOW_TRAVELER)
		strSSLPassword.Set(KEY_PASSWORD);

		OTString strClientPath(strPath.Get());
        g_OT_API.Init(strClientPath);  // SSL gets initialized in here, before any keys are loaded.
#else
		exit(1);
#endif
	}
	else if (argc < 3)
	{
		OTLog::vOutput(0, "\n==> USAGE:    %s   <SSL-password>  <absolute_path_to_data_folder>\n\n"
#if defined (FELLOW_TRAVELER)					      
				"(Folder defaults to '%s' if left blank.)\n"
#endif
					   "\n\n", argv[0]
#if defined (FELLOW_TRAVELER)
					   , strPath.Get()
#endif
					   );
		
#if defined (FELLOW_TRAVELER)					   
		strSSLPassword.Set(argv[1]);

		OTString strClientPath(strPath.Get());
        g_OT_API.Init(strClientPath);  // SSL gets initialized in here, before any keys are loaded.
#else
		exit(1);
#endif
	}
	else 
	{
		strSSLPassword.Set(argv[1]);

		OTString strClientPath(argv[2]);
        g_OT_API.Init(strClientPath);  // SSL gets initialized in here, before any keys are loaded.
	}	

	OTLog::vOutput::(0, "Using as path to data folder:  %s\n", OTLog::Path());

	strCAFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), CA_FILE);
	strKeyFile.Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), KEY_FILE);


	// ------------------------------------------------------------------------------

	//
	// Basically, loop:
	//
	//	1) Present a prompt, and get a user string of input. Wait for that.
	//
	//	2) Process it out as an OTMessage to the server. It goes down the pipe.
	//
	//	3) Sleep for 1 second.
	//
	//	4) Awake and check for messages to be read in response from the server.
	//	   Loop. As long as there are any responses there, then process and handle
	//	   them all.
	//	   Then continue back up to the prompt at step (1).

    char buf[200] = "";
 	int retVal = 0;

	int nExpectResponse = 0;

	OTLog::Output(0, "You may wish to 'load' then 'connect' then 'stat'.\n");
	OTLog::vOutput(4, "Starting client loop. u_header size in C code is %d.\n", OT_CMD_HEADER_SIZE);


	for(;;)
	{
		buf[0] = 0; // Making it fresh again.

		nExpectResponse = 0;

		// 1) Present a prompt, and get a user string of input. Wait for that.
		OTLog::Output(0, "\nWallet> ");

		if (NULL == fgets(buf, sizeof(buf)-10, stdin)) // Leaving myself 10 extra bytes at the end for safety's sake.
            break;

		OTLog::Output(0, ".\n..\n...\n....\n.....\n......\n.......\n........\n.........\n..........\n"
				"...........\n............\n.............\n");

		// so we can process the user input
		std::string strLine = buf;

		// 1.5 The one command that doesn't involve a message to the server (so far)
		//     is the command to load the wallet from disk (which we do before we can
		//     do anything else.)  That and maybe the message to CONNECT to the server.
		// Load wallet.xml
		if (strLine.compare(0,4,"load") == 0)
		{
			OTLog::Output(0, "User has instructed to load wallet.xml...\n");
			g_OT_API.GetWallet()->LoadWallet("wallet.xml");
 
//			g_OT_API.GetWallet()->SaveWallet("NEWwallet.xml"); // todo remove this test code.

			continue;
		}

		else if (strLine.compare(0,5,"clear") == 0)
		{
			if (NULL == g_pTemporaryNym)
			{
				OTLog::Output(0, "No Nym yet available. Try 'load'.\n");
				continue;
			}

			g_pTemporaryNym->RemoveAllNumbers();

			g_pTemporaryNym->SaveSignedNymfile(*g_pTemporaryNym);

			OTLog::Output(0, "Successfully removed all issued and transaction numbers. Saving nym...\n");

			continue;
		}			

		else if (strLine.compare(0,7,"payment") == 0)
		{
			if (NULL == g_pTemporaryNym)
			{
				OTLog::Output(0, "No Nym yet available to sign the payment plan with. Try 'load'.\n");
				continue;
			}

			OTLog::Output(0, "Enter your Asset Account ID that the payments will come from: ");
			OTString strTemp;
			strTemp.OTfgets(std::cin);

			const OTIdentifier ACCOUNT_ID(strTemp), USER_ID(*g_pTemporaryNym);
			OTAccount * pAccount = g_OT_API.GetWallet()->GetAccount(ACCOUNT_ID);

			if (NULL == pAccount)
			{
				OTLog::Output(0, "That account isn't loaded right now. Try 'load'.\n");
				continue;
			}

			// To write a payment plan, like a cheque, we need to burn one of our transaction numbers. (Presumably
			// the wallet is also storing a couple of these, since they are needed to perform any transaction.)
			//
			// I don't have to contact the server to write a payment plan -- as long as I already have a transaction
			// number I can use to write it. Otherwise I'd have to ask the server to send me one first.
			OTString strServerID(pAccount->GetRealServerID());
			long lTransactionNumber=0;

			if (false == g_pTemporaryNym->GetNextTransactionNum(*g_pTemporaryNym, strServerID, lTransactionNumber))
			{
				OTLog::Output(0, "Payment Plans are written offline, but you still need a transaction number\n"
							  "(and you have none, currently.) Try using 'n' to request another transaction number.\n");
				continue;
			}

			// -----------------------------------------------------------------------

			OTString str_RECIPIENT_USER_ID, str_RECIPIENT_ACCT_ID, strConsideration;

			// Get the Recipient Nym ID
			OTLog::Output(0, "Enter the Recipient's User ID (NymID): ");
			str_RECIPIENT_USER_ID.OTfgets(std::cin);		


			// THEN GET AN ACCOUNT ID in that same asset type
			OTLog::Output(0, "Enter the Recipient's ACCOUNT ID (of the same asset type as your account): ");
			str_RECIPIENT_ACCT_ID.OTfgets(std::cin);		

			OTLog::Output(0, "Enter a memo describing consideration for the payment plan: ");
			strConsideration.OTfgets(std::cin);		

			const OTIdentifier	RECIPIENT_USER_ID(str_RECIPIENT_USER_ID), 
								RECIPIENT_ACCT_ID(str_RECIPIENT_ACCT_ID);


			OTPaymentPlan thePlan(pAccount->GetRealServerID(), pAccount->GetAssetTypeID(),
								  pAccount->GetRealAccountID(),	pAccount->GetUserID(),
								  RECIPIENT_ACCT_ID, RECIPIENT_USER_ID);

			// -----------------------------------------------------------------------

			// Valid date range (in seconds)
			OTLog::Output(0, 
						  " 6 minutes	==      360 Seconds\n"
						  "10 minutes	==      600 Seconds\n"
						  "1 hour		==     3600 Seconds\n"
						  "1 day		==    86400 Seconds\n"
						  "30 days			==  2592000 Seconds\n"
						  "3 months		==  7776000 Seconds\n"
						  "6 months		== 15552000 Seconds\n\n"
						  );

			long lExpirationInSeconds = 86400;
			OTLog::vOutput(0, "How many seconds before payment plan expires? (defaults to 1 day: %ld): ", lExpirationInSeconds);
			strTemp.Release();
			strTemp.OTfgets(std::cin);

			if (strTemp.GetLength() > 1)
				lExpirationInSeconds = atol(strTemp.Get());


			// -----------------------------------------------------------------------

			time_t	VALID_FROM	= time(NULL); // This time is set to TODAY NOW

			OTLog::vOutput(0, "Payment plan becomes valid for processing STARTING date\n"
						   "(defaults to now, in seconds) [%ld]: ", VALID_FROM);
			strTemp.Release();
			strTemp.OTfgets(std::cin);

			if (strTemp.GetLength() > 2)
				VALID_FROM = atol(strTemp.Get());

			const time_t VALID_TO = VALID_FROM + lExpirationInSeconds; // now + 86400

			// -----------------------------------------------------------------------

			bool bSuccessSetAgreement = thePlan.SetAgreement(lTransactionNumber, strConsideration, VALID_FROM,	VALID_TO);

			if (!bSuccessSetAgreement)
			{
				OTLog::Output(0, "Failed trying to set the agreement!\n");

				// IF FAILED, ADD TRANSACTION NUMBER BACK TO LIST OF AVAILABLE NUMBERS.
				g_pTemporaryNym->AddTransactionNum(*g_pTemporaryNym, strServerID, lTransactionNumber, true); // bSave=true								

				continue;
			}

			bool bSuccessSetInitialPayment	= true; // the default, in case user chooses not to even have this payment.
			bool bSuccessSetPaymentPlan		= true; // the default, in case user chooses not to have a payment plan
			// -----------------------------------------------------------------------

			OTLog::Output(0, "What is the Initial Payment Amount, if any? [0]: ");
			strTemp.Release(); strTemp.OTfgets(std::cin);
			long lInitialPayment = atol(strTemp.Get());

			if (lInitialPayment > 0)
			{
				time_t	PAYMENT_DELAY = 60; // 60 seconds.

				OTLog::vOutput(0, "From the Start Date forward, how long until the Initial Payment should charge?\n"
							   "(defaults to one minute, in seconds) [%d]: ", PAYMENT_DELAY);
				strTemp.Release();
				strTemp.OTfgets(std::cin);

				if ((strTemp.GetLength() > 1) && atol(strTemp.Get())>0)
					PAYMENT_DELAY = atol(strTemp.Get());

				// -----------------------------------------------------------------------

				 bSuccessSetInitialPayment = thePlan.SetInitialPayment(lInitialPayment, PAYMENT_DELAY);
			}

			if (!bSuccessSetInitialPayment)
			{
				OTLog::Output(0, "Failed trying to set the initial payment!\n");

				// IF FAILED, ADD TRANSACTION NUMBER BACK TO LIST OF AVAILABLE NUMBERS.
				g_pTemporaryNym->AddTransactionNum(*g_pTemporaryNym, strServerID, lTransactionNumber, true); // bSave=true								

				continue;
			}

			// -----------------------------------------------------------------------

			OTLog::Output(0, "What is the regular payment amount, if any? [0]: ");
			strTemp.Release(); strTemp.OTfgets(std::cin);
			long lRegularPayment = atol(strTemp.Get());

			if (lRegularPayment > 0) // If there are regular payments.
			{
				// -----------------------------------------------------------------------

				time_t	PAYMENT_DELAY = 120; // 120 seconds.

				OTLog::vOutput(0, "From the Start Date forward, how long until the Regular Payments start?\n"
							   "(defaults to two minutes, in seconds) [%d]: ", PAYMENT_DELAY);
				strTemp.Release();
				strTemp.OTfgets(std::cin);

				if ((strTemp.GetLength() > 1) && atol(strTemp.Get())>0)
					PAYMENT_DELAY = atol(strTemp.Get());

				// -----------------------------------------------------------------------

				time_t	PAYMENT_PERIOD = 30; // 30 seconds.

				OTLog::vOutput(0, "Once payments begin, how much time should elapse between each payment?\n"
							   "(defaults to thirty seconds) [%d]: ", PAYMENT_PERIOD);
				strTemp.Release();
				strTemp.OTfgets(std::cin);

				if ((strTemp.GetLength() > 1) && atol(strTemp.Get())>0)
					PAYMENT_PERIOD = atol(strTemp.Get());

				// -----------------------------------------------------------------------

				time_t	PLAN_LENGTH = 0; // 0 seconds (for no max length).

				OTLog::vOutput(0, "From start date, do you want the plan to expire after a certain maximum time?\n"
							   "(defaults to 0 for no) [%d]: ", PLAN_LENGTH);
				strTemp.Release();
				strTemp.OTfgets(std::cin);

				if (strTemp.GetLength() > 1)
					PLAN_LENGTH = atol(strTemp.Get());

				// -----------------------------------------------------------------------

				OTLog::Output(0, "Should there be some maximum number of payments? (Zero for no maximum.) [0]: ");
				strTemp.Release(); strTemp.OTfgets(std::cin);
				int nMaxPayments = atoi(strTemp.Get());

				bSuccessSetPaymentPlan = thePlan.SetPaymentPlan(lRegularPayment, PAYMENT_DELAY, PAYMENT_PERIOD, PLAN_LENGTH, nMaxPayments);
			}

			if (!bSuccessSetPaymentPlan)
			{
				OTLog::Output(0, "Failed trying to set the payment plan!\n");

				// IF FAILED, ADD TRANSACTION NUMBER BACK TO LIST OF AVAILABLE NUMBERS.
				g_pTemporaryNym->AddTransactionNum(*g_pTemporaryNym, strServerID, lTransactionNumber, true); // bSave=true								

				continue;
			}

			thePlan.SignContract(*g_pTemporaryNym);
			thePlan.SaveContract();

			OTString strPlan(thePlan);

			OTLog::vOutput(0, "\n\n(Make sure Both Parties sign the payment plan before submitting to server):\n\n\n%s\n", 
						   strPlan.Get());

			continue;			
		}


		else if (strLine.compare(0,6,"cheque") == 0)
		{
			if (NULL == g_pTemporaryNym)
			{
				OTLog::Output(0, "No Nym yet available to sign the cheque with. Try 'load'.\n");
				continue;
			}


			OTLog::Output(0, "Enter the ID for your Asset Account that the cheque will be drawn on: ");
			OTString strTemp;
			strTemp.OTfgets(std::cin);

			const OTIdentifier ACCOUNT_ID(strTemp), USER_ID(*g_pTemporaryNym);
			OTAccount * pAccount = g_OT_API.GetWallet()->GetAccount(ACCOUNT_ID);

			if (NULL == pAccount)
			{
				OTLog::Output(0, "That account isn't loaded right now. Try 'load'.\n");
				continue;
			}

			// To write a cheque, we need to burn one of our transaction numbers. (Presumably the wallet
			// is also storing a couple of these, since they are needed to perform any transaction.)
			//
			// I don't have to contact the server to write a cheque -- as long as I already have a transaction
			// number I can use to write it. Otherwise I'd have to ask the server to send me one first.
			OTString strServerID(pAccount->GetRealServerID());
			long lTransactionNumber=0;

			if (false == g_pTemporaryNym->GetNextTransactionNum(*g_pTemporaryNym, strServerID, lTransactionNumber))
			{
				OTLog::Output(0, "Cheques are written offline, but you still need a transaction number\n"
						"(and you have none, currently.) Try using 'n' to request another transaction number.\n");
				continue;
			}


			OTCheque theCheque(pAccount->GetRealServerID(), pAccount->GetAssetTypeID());

			// Recipient
			OTLog::Output(0, "Enter a User ID for the recipient of this cheque (defaults to blank): ");
			OTString strRecipientUserID;
			strRecipientUserID.OTfgets(std::cin);
			const OTIdentifier RECIPIENT_USER_ID(strRecipientUserID.Get());

			// Amount
			OTLog::Output(0, "Enter an amount: ");
			strTemp.Release();
			strTemp.OTfgets(std::cin);
			const long lAmount = atol(strTemp.Get());

			// -----------------------------------------------------------------------

			// Memo
			OTLog::Output(0, "Enter a memo for your check: ");
			OTString strChequeMemo;
			strChequeMemo.OTfgets(std::cin);

			// -----------------------------------------------------------------------

			// Valid date range (in seconds)
			OTLog::Output(0, 
					" 6 minutes	==      360 Seconds\n"
					"10 minutes	==      600 Seconds\n"
					"1 hour		==     3600 Seconds\n"
					"1 day		==    86400 Seconds\n"
					"30 days	==  2592000 Seconds\n"
					"3 months	==  7776000 Seconds\n"
					"6 months	== 15552000 Seconds\n\n"
					);

			long lExpirationInSeconds = 3600;
			OTLog::vOutput(0, "How many seconds before cheque expires? (defaults to 1 hour: %ld): ", lExpirationInSeconds);
			strTemp.Release();
			strTemp.OTfgets(std::cin);

			if (strTemp.GetLength() > 1)
				lExpirationInSeconds = atol(strTemp.Get());


			// -----------------------------------------------------------------------

			time_t	VALID_FROM	= time(NULL); // This time is set to TODAY NOW

			OTLog::vOutput(0, "Cheque may be cashed STARTING date (defaults to now, in seconds) [%ld]: ", VALID_FROM);
			strTemp.Release();
			strTemp.OTfgets(std::cin);

			if (strTemp.GetLength() > 2)
				VALID_FROM = atol(strTemp.Get());


			const time_t VALID_TO = VALID_FROM + lExpirationInSeconds; // now + 3600

			// -----------------------------------------------------------------------

			bool bIssueCheque = theCheque.IssueCheque(lAmount, lTransactionNumber, VALID_FROM, VALID_TO, 
													  ACCOUNT_ID, USER_ID, strChequeMemo,
													  (strRecipientUserID.GetLength() > 2) ? &(RECIPIENT_USER_ID) : NULL);

			if (bIssueCheque)
			{
				theCheque.SignContract(*g_pTemporaryNym);
				theCheque.SaveContract();

				OTString strCheque(theCheque);

				OTLog::vOutput(0, "\n\nOUTPUT:\n\n\n%s\n", strCheque.Get());
			}
			else 
			{
				OTLog::Output(0, "Failed trying to issue the cheque!\n");

				// IF FAILED, ADD TRANSACTION NUMBER BACK TO LIST OF AVAILABLE NUMBERS.
				g_pTemporaryNym->AddTransactionNum(*g_pTemporaryNym, strServerID, lTransactionNumber, true); // bSave=true								
			}

			continue;
		}

		else if (strLine.compare(0,7,"decrypt") == 0)
		{
			if (NULL == g_pTemporaryNym)
			{
				OTLog::Output(0, "No Nym yet available to decrypt with.\n");
				continue;
			}

			OTLog::Output(0, "Enter text to be decrypted:\n> ");

			OTASCIIArmor theArmoredText;
			char decode_buffer[200]; // Safe since we only read sizeof - 1

			do {
				decode_buffer[0] = 0;
				if (NULL != fgets(decode_buffer, sizeof(decode_buffer)-1, stdin))
				{
					theArmoredText.Concatenate("%s\n", decode_buffer);
					OTLog::Output(0, "> ");
				}
				else 
				{
					break;
				}
			} while (strlen(decode_buffer)>1);


			OTEnvelope	theEnvelope(theArmoredText);
			OTString	strDecodedText;

			theEnvelope.Open(*g_pTemporaryNym, strDecodedText);

			OTLog::vOutput(0, "\n\nDECRYPTED TEXT:\n\n%s\n\n", strDecodedText.Get());

			continue;
		}

		else if (strLine.compare(0,6,"decode") == 0)
		{
			OTLog::Output(0, "Enter text to be decoded:\n> ");

			OTASCIIArmor theArmoredText;
			char decode_buffer[200]; // Safe since we only read sizeof - 1.

			do {
				decode_buffer[0] = 0;
				if (NULL != fgets(decode_buffer, sizeof(decode_buffer)-1, stdin))
				{
					theArmoredText.Concatenate("%s\n", decode_buffer);
					OTLog::Output(0, "> ");
				}
				else 
				{
					break;
				}

			} while (strlen(decode_buffer)>1);

			OTString strDecodedText(theArmoredText);

			OTLog::vOutput(0, "\n\nDECODED TEXT:\n\n%s\n\n", strDecodedText.Get());

			continue;
		}

		else if (strLine.compare(0,6,"encode") == 0)
		{
			OTLog::Output(0, "Enter text to be ascii-encoded (terminate with ~ on a new line):\n> ");

			OTString strDecodedText;
			char decode_buffer[200]; // Safe since we only read sizeof - 1.

			do {
				decode_buffer[0] = 0;

				if ((NULL != fgets(decode_buffer, sizeof(decode_buffer)-1, stdin)) &&
					(decode_buffer[0] != '~'))
				{
					strDecodedText.Concatenate("%s", decode_buffer);
					OTLog::Output(0, "> ");
				}
				else 
				{
					break;
				}

			} while (decode_buffer[0] != '~');

			OTASCIIArmor theArmoredText(strDecodedText);

			OTLog::vOutput(0, "\n\nENCODED TEXT:\n\n%s\n\n", theArmoredText.Get());

			continue;
		}

		else if (strLine.compare(0,4,"hash") == 0)
		{
			OTLog::Output(0, "Enter text to be hashed (terminate with ~ on a new line):\n> ");

			OTString strDecodedText;
			char decode_buffer[200]; // Safe since we only read sizeof - 1.

			do {
				decode_buffer[0] = 0;

				if ((NULL != fgets(decode_buffer, sizeof(decode_buffer)-1, stdin)) &&
					(decode_buffer[0] != '~'))
				{
					strDecodedText.Concatenate("%s\n", decode_buffer);
					OTLog::Output(0, "> ");
				}
				else 
				{
					break;
				}

			} while (decode_buffer[0] != '~');

			OTIdentifier theIdentifier;
			theIdentifier.CalculateDigest(strDecodedText);

			OTString strHash(theIdentifier);

			OTLog::vOutput(0, "\n\nMESSAGE DIGEST:\n\n%s\n\n", strHash.Get());

			continue;
		}

		else if (strLine.compare(0,4,"stat") == 0)
		{
			OTLog::Output(0, "User has instructed to display wallet contents...\n");

			OTString strStat;
			g_OT_API.GetWallet()->DisplayStatistics(strStat);
			OTLog::vOutput(0, "%s\n", strStat.Get());

			continue;
		}

		else if (strLine.compare(0,4,"help") == 0)
		{
			OTLog::Output(0, "User has instructed to display the help file...\n");

			system("more ../docs/CLIENT-COMMANDS.txt");

			continue;
		}

		else if (strLine.compare(0,4,"quit") == 0)
		{
			OTLog::Output(0, "User has instructed to exit the wallet...\n");

			break;
		}

		// 1.6 Connect to the first server in the wallet. (assuming it loaded a server contract.)
		else if (strLine.compare(0,7,"connect") == 0)
		{
			OTLog::Output(0, "User has instructed to connect to the first server available in the wallet.\n");

			if (NULL == g_pTemporaryNym)
			{
				OTLog::Output(0, "No Nym yet available to connect with. Try 'load'.\n");
				continue;
			}

			// Wallet, after loading, should contain a list of server
			// contracts. Let's pull the hostname and port out of
			// the first contract, and connect to that server.
			bool bConnected = g_OT_API.GetClient()->ConnectToTheFirstServerOnList(*g_pTemporaryNym, strCAFile, strKeyFile, strSSLPassword); 

			if (bConnected)
				OTLog::Output(0, "Success. (Connected to the first notary server on your wallet's list.)\n");
			else {
				OTLog::Output(0, "Either the wallet is not loaded, or there was an error connecting to server.\n");
			}

			continue;
		}

		if (!g_OT_API.GetClient()->IsConnected())
		{
			OTLog::Output(0, "(You are not connected to a notary server--you cannot send commands.)\n");
			continue;
		}

		// 2) Process it out as an OTMessage to the server. It goes down the pipe.
		g_OT_API.GetClient()->ProcessMessageOut(buf, &nExpectResponse);
		
		// 3) Sleep for 1 second.
#ifdef _WIN32
		OT_Sleep(1000);
#else
		sleep (1);
#endif

		bool bFoundMessage = false;

		// 4) While there are messages to be read in response from the server,
		//	  then process and handle them all.
		do 
		{
			OTMessage * pMsg = new OTMessage;

			OT_ASSERT(NULL != pMsg);

			// If this returns true, that means a Message was
			// received and processed into an OTMessage object (theMsg)
			bFoundMessage = g_OT_API.GetClient()->ProcessInBuffer(*pMsg);

			if (true == bFoundMessage)
			{
//				OTString strReply;
//				theMsg.SaveContract(strReply);
//				OTLog::vOutput(0, "\n\n**********************************************\n"
//						"Successfully in-processed server response.\n\n%s\n", strReply.Get());
				g_OT_API.GetClient()->ProcessServerReply(*pMsg); // the Client takes ownership and will handle cleanup.
			}
			else 
			{
				delete pMsg;
				pMsg = NULL;
			}


		} while (true == bFoundMessage);
	} // for

	OTLog::Output(0, "Finished running client.\n");

#ifdef _WIN32
	WSACleanup();
#endif

	return retVal;
}
Пример #29
0
bool OTEnvelope::Decrypt(OTString & theOutput, const OTSymmetricKey & theKey, const OTPassword & thePassword)
{
    const char * szFunc = "OTEnvelope::Decrypt";
    // ------------------------------------------------
    OT_ASSERT((thePassword.isPassword() && (thePassword.getPasswordSize() > 0)) || (thePassword.isMemory() && (thePassword.getMemorySize() > 0)));
    OT_ASSERT(theKey.IsGenerated());
    // -----------------------------------------------
    OTPassword  theRawSymmetricKey;
    
    if (false == theKey.GetRawKeyFromPassphrase(thePassword, theRawSymmetricKey))
    {
		OTLog::vError("%s: Failed trying to retrieve raw symmetric key using password. (Wrong password?)\n", 
                      szFunc);
		return false;	
    }
    // -----------------------------------------------
    //
    uint32_t    nRead         = 0;
    uint32_t    nRunningTotal = 0;
    
    m_dataContents.reset(); // Reset the fread position on this object to 0.

    // ****************************************************************************
    //
    // Read the ENVELOPE TYPE (as network order version -- and convert to host version.)
    //
    // 0 == Error
    // 1 == Asymmetric Key  (this function -- Seal / Open)
    // 2 == Symmetric Key   (other functions -- Encrypt / Decrypt use this.)
    // Anything else: error.
    //
    uint16_t  env_type_n = 0;
    
    if (0 == (nRead = m_dataContents.OTfread(reinterpret_cast<uint8_t*>(&env_type_n),
                                             static_cast<uint32_t>(sizeof(env_type_n)))))
	{
		OTLog::vError("%s: Error reading Envelope Type. Expected asymmetric(1) or symmetric (2).\n", szFunc);
		return false;
	}
    nRunningTotal += nRead;
    OT_ASSERT(nRead == static_cast<uint32_t>(sizeof(env_type_n)));
    // ----------------------------------------------------------------------------
	// convert that envelope type from network to HOST endian.
    //
    const uint16_t env_type = static_cast<uint16_t>(ntohs(static_cast<uint16_t>(env_type_n)));
//  nRunningTotal += env_type;    // NOPE! Just because envelope type is 1 or 2, doesn't mean we add 1 or 2 extra bytes to the length here. Nope!
    
    if (2 != env_type)
	{
        const uint32_t l_env_type = static_cast<uint32_t>(env_type);
		OTLog::vError("%s: Error: Expected Envelope for Symmetric key (type 2) but instead found type: %ld.\n", 
                      szFunc, l_env_type);
		return false;
	}
    // ****************************************************************************
    //
    // Read network-order IV size (and convert to host version) 
    //    
    const uint32_t max_iv_length   = OTCryptoConfig::SymmetricIvSize(); // I believe this is a max length, so it may not match the actual length of the IV.
    
    // Read the IV SIZE (network order version -- convert to host version.)
    //
    uint32_t	iv_size_n   = 0;
    
    if (0 == (nRead = m_dataContents.OTfread(reinterpret_cast<uint8_t*>(&iv_size_n),
                                             static_cast<uint32_t>(sizeof(iv_size_n)))))
	{
		OTLog::vError("%s: Error reading IV Size.\n", szFunc);
		return false;
	}
    nRunningTotal += nRead;
    OT_ASSERT(nRead == static_cast<uint32_t>(sizeof(iv_size_n)));
    // ----------------------------------------------------------------------------
	// convert that iv size from network to HOST endian.
    //
    const uint32_t iv_size_host_order = ntohl(iv_size_n);
    
    if (iv_size_host_order > max_iv_length)
    {
        OTLog::vError("%s: Error: iv_size (%ld) is larger than max_iv_length (%ld).\n",
                      szFunc, static_cast<long>(iv_size_host_order), static_cast<long>(max_iv_length));
        return false;
    }
//  nRunningTotal += iv_size_host_order; // Nope!
    // ****************************************************************************
    //
    // Then read the IV (initialization vector) itself.
    //
    OTPayload theIV;
    theIV.SetPayloadSize(iv_size_host_order);
    
    if (0 == (nRead = m_dataContents.OTfread(static_cast<uint8_t*>(const_cast<void *>(theIV.GetPayloadPointer())), 
                                             static_cast<uint32_t>(iv_size_host_order))))
    {
        OTLog::vError("%s: Error reading initialization vector.\n", szFunc);
        return false;
    }
    nRunningTotal += nRead;
    OT_ASSERT(nRead == static_cast<uint32_t>(iv_size_host_order));
    
    OT_ASSERT(nRead <= max_iv_length);
    
	// ----------------------------------------------------------------------------    
    // We create an OTPayload object to store the ciphertext itself, which begins AFTER the end of the IV.
    // So we see pointer + nRunningTotal as the starting point for the ciphertext.
    // the size of the ciphertext, meanwhile, is the size of the entire thing, MINUS nRunningTotal.
    //
	OTPayload theCipherText(static_cast<const void*>( 
                                               static_cast<const uint8_t *>(m_dataContents.GetPointer()) + nRunningTotal
                                               ), 
					  m_dataContents.GetSize() - nRunningTotal);
    // ----------------------------------------------------------------------------
    // Now we've got all the pieces together, let's try to decrypt it...
    //
    OTPayload thePlaintext; // for output.
    
    const bool bDecrypted = OTCrypto::It()->Decrypt(theRawSymmetricKey, // The symmetric key, in clear form.
                                                    // -------------------------------
                                                    static_cast<const char *>(theCipherText.GetPayloadPointer()),  // This is the Ciphertext.
                                                    theCipherText.GetSize(),
                                                    // -------------------------------
                                                    theIV,
                                                    // -------------------------------
                                                    thePlaintext); // OUTPUT. (Recovered plaintext.) You can pass OTPassword& OR OTPayload& here (either will work.)
    // -----------------------------------------------
    // theOutput is where we'll put the decrypted data.
    //
    theOutput.Release();
    
    if (bDecrypted)
    {
        // -----------------------------------------------------
        // Make sure it's null-terminated...
        //
        uint32_t nIndex = thePlaintext.GetSize()-1;
        (static_cast<uint8_t*>(const_cast<void *>(thePlaintext.GetPointer())))[nIndex] = '\0';
        
        // -----------------------------------------------------
        // Set it into theOutput (to return the plaintext to the caller)
        //
        theOutput.Set(static_cast<const char *>(thePlaintext.GetPointer()));
        // ----------------
    }
    
    return bDecrypted;
}