Cant cout the result that what I want with MySQL and c++ - c++

#include <iostream>
#include <Windows.h>
#include "jdbc/mysql_connection.h"
#include "jdbc/cppconn/driver.h"
#include "jdbc/cppconn/exception.h"
#include "jdbc/cppconn/resultset.h"
#include "jdbc/cppconn/statement.h"
#include "jdbc/cppconn/prepared_statement.h"
#ifdef _DEBUG
#pragma comment(lib, "debug/mysqlcppconn.lib")
#else
#pragma comment(lib, "mysqlcppconn.lib")
#endif
using namespace std;
std::string Utf8ToMultiByte(std::string utf8_str);
int main()
{
try
{
sql::Driver* driver;
sql::Connection* connection;
sql::Statement* statement;
sql::ResultSet* resultset;
driver = get_driver_instance();
connection = driver->connect("tcp://127.0.0.1:3306", "root", "");
if (connection == nullptr)
{
cout << "connect failed" << endl;
exit(-1);
}
connection->setSchema("logindata");
statement = connection->createStatement();
resultset = statement->executeQuery("insert into new_table(number, id, wincount, totalgameplay) values(4, 132, 232349, 123)");
resultset = statement->executeQuery("select * from new_table ");
for (;resultset->next();)
{
cout << resultset->getInt("id") << " : " <<
Utf8ToMultiByte(resultset->getString("wincount")) << " : " <<
Utf8ToMultiByte(resultset->getString("totalgameplay")) << endl;
}
delete resultset;
delete statement;
delete connection;
}
catch (sql::SQLException e)
{
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
return 0;
}
std::string Utf8ToMultiByte(std::string utf8_str)
{
std::string resultString; char* pszIn = new char[utf8_str.length() + 1];
strncpy_s(pszIn, utf8_str.length() + 1, utf8_str.c_str(), utf8_str.length());
int nLenOfUni = 0, nLenOfANSI = 0; wchar_t* uni_wchar = NULL;
char* pszOut = NULL;
// 1. utf8 Length
if ((nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), NULL, 0)) <= 0)
return nullptr;
uni_wchar = new wchar_t[nLenOfUni + 1];
memset(uni_wchar, 0x00, sizeof(wchar_t)*(nLenOfUni + 1));
// 2. utf8 --> unicode
nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), uni_wchar, nLenOfUni);
// 3. ANSI(multibyte) Length
if ((nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, NULL, 0, NULL, NULL)) <= 0)
{
delete[] uni_wchar; return 0;
}
pszOut = new char[nLenOfANSI + 1];
memset(pszOut, 0x00, sizeof(char)*(nLenOfANSI + 1));
// 4. unicode --> ANSI(multibyte)
nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, pszOut, nLenOfANSI, NULL, NULL);
pszOut[nLenOfANSI] = 0;
resultString = pszOut;
delete[] uni_wchar;
delete[] pszOut;
return resultString;
}
why I cant get result of table information?
does insert and select then cout is not proper process?
Also I try with PrepareStatement with above the select phrase. But I worked properly
I know that preparestatement and createstatement is different with dynamic parsing and static parsing. what is more efficient with adding information to database?

Related

How can I connect MySQL with using socket programming in C++

I am newbie in programming world. I am trying to make Login system with C++ so I try to connect MySQL database with my server program. without using socket I can connect with database well. But my Final Goal is to success login to my local server and add information to my DB.
I found that if I add "driver.h" from MySQL Connector 8.0, It said the connection is gone. actually it cant connect to socket. but when I comment out the "driver.h" hearder, It connect to socket well. but without "driver.h", I cant connect to my DB.
What is the problem and How can I solve it? the version of VS is 2022, and MySQL version is 8.0.30. Below is my full Code of Client and Server.
And sorry I cant emebed image still I am newbie here
[So I post in Notion][1]:https://sunny-green-970.notion.site/Error-ea96fbef0ea64e1bb1fd966699657547
Client
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN ServerAddrIn;
memset(&ServerAddrIn, 0, sizeof(SOCKADDR_IN));
ServerAddrIn.sin_family = PF_INET;
ServerAddrIn.sin_addr.s_addr = inet_addr("127.0.0.1");
ServerAddrIn.sin_port = htons(1234);
printf("client\n");
if (connect(ServerSocket, (SOCKADDR*)&ServerAddrIn, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) // 자기 ip와 port 필요없다. 서버에 접속하면 된다.
{
std::cout << "Connect Failed." << std::endl;
exit(-1);
}
int Numnber = 0;
int WinCount = 0;
int TotalGamePlay = 0;
//connect(ServerSocket, (SOCKADDR*)&ServerAddrIn, sizeof(SOCKADDR_IN));
printf("Please Type Number: ");
scanf("%d", &Numnber);
printf("Please Type WinCount: ");
scanf("%d", &WinCount);
printf("Please Type TotalGamePlay: ");
scanf("%d", &TotalGamePlay);
char Buffer[1024] = { 0, };
memcpy(Buffer, &Numnber, 4);
memcpy(&Buffer[4], &WinCount, 4);
memcpy(&Buffer[8], &TotalGamePlay, 4);
int SentLength = send(ServerSocket, Buffer, 12, 0);
printf("Sent Length : %d\n", SentLength);
if (SentLength == 0)
{
//연결 종료s
std::cout << "Disconnected Client." << std::endl;
}
else if (SentLength < 0)
{
//Error
std::cout << "Disconnected Client By Error : " << GetLastError() << std::endl;
}
WSACleanup();
return 0;
}
Server
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include "jdbc/mysql_connection.h"
#include "jdbc/cppconn/exception.h"
#include "jdbc/cppconn/resultset.h"
#include "jdbc/cppconn/statement.h"
#include "jdbc/cppconn/prepared_statement.h"
#include "jdbc/cppconn/driver.h"
#pragma comment(lib, "ws2_32.lib")
#ifdef _DEBUG
#pragma comment(lib, "debug/mysqlcppconn.lib")
#else
#pragma comment(lib, "mysqlcppconn.lib")
#endif
using namespace std;
std::string Utf8ToMultiByte(std::string utf8_str);
int main()
{
bool bRunning = true;
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN ServerAddrIn;
memset(&ServerAddrIn, 0, sizeof(SOCKADDR_IN));
ServerAddrIn.sin_family = AF_INET;
ServerAddrIn.sin_port = htons(1234);
ServerAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
fd_set Original;
fd_set CopyReads;
timeval Timeout;
Timeout.tv_sec = 0;
Timeout.tv_usec = 10;
FD_ZERO(&Original);
FD_SET(ServerSocket, &Original);
bind(ServerSocket, (SOCKADDR*)&ServerAddrIn, sizeof(SOCKADDR_IN));
listen(ServerSocket, 0);
printf("Server\n");
while (bRunning)
{
CopyReads = Original;
//polling
int fd_num = select(0, &CopyReads, 0, 0, &Timeout);
if (fd_num == 0)
{
continue;
}
if (fd_num == SOCKET_ERROR)
{
bRunning = false;
break;
}
for (size_t i = 0; i < Original.fd_count; ++i)
{
//등록한 소켓 리스트 중에 이벤트 발생 했음
if (FD_ISSET(Original.fd_array[i], &CopyReads))
{
if (Original.fd_array[i] == ServerSocket)
{
//서버 소켓에 이벤트가 발생함, 연결 요청
SOCKADDR_IN ClientSockAddrIn;
memset((char*)&ClientSockAddrIn, 0, sizeof(SOCKADDR_IN));
int ClientSockAddrInSize = sizeof(SOCKADDR_IN);
SOCKET ClientSocket = accept(ServerSocket, (SOCKADDR*)&ClientSockAddrIn, &ClientSockAddrInSize);
FD_SET(ClientSocket, &Original);
std::cout << "Connected client : " << ClientSocket << std::endl;
}
else
{
SOCKET ClientSocket = Original.fd_array[i];
//Client 소켓, Recv, Send
char Buffer[1024] = { 0, };
//blocking, non blocking
//packet 설계, protocol
int RecvLength = recv(ClientSocket, Buffer, sizeof(Buffer), 0);
if (RecvLength == 0)
{
//연결 종료
std::cout << "Disconnected Client." << std::endl;
FD_CLR(ClientSocket, &Original);
closesocket(ClientSocket);
}
else if (RecvLength < 0)
{
//Error
std::cout << "Disconnected Client By Error : " << GetLastError() << std::endl;
FD_CLR(ClientSocket, &Original);
closesocket(ClientSocket);
}
else
{
//자료가 있으면 처리
//packet parse
int number = 0;
int wincount = 0;
int totalgameplay = 0;
memcpy(&number, &buffer[0], 4);
memcpy(&wincount, &buffer[4], 4);
memcpy(&totalgameplay, &buffer[8], 4);
try
{
sql::driver* driver; //workbench
sql::connection* connection; //접속
sql::statement* statement; //query
sql::resultset* resultset; //결과화면
sql::preparedstatement* preparedstatement;
//work벤치 켜기
driver = get_driver_instance();
//연결 버튼 누르기
connection = driver->connect("tcp://127.0.0.1:3306", "root", "secret");
if (connection == nullptr)
{
cout << "connect failed" << endl;
exit(-1);
}
사용 데이터베이스 선정(use)
connection->setschema("logindata");
preparedstatement = connection->preparestatement("insert into new_table(number, wincount, totalgameplay) values( ?, ? ,?)");
preparedstatement->setint(1, number);
preparedstatement->setint(2, wincount);
preparedstatement->setint(3, totalgameplay);
preparedstatement->executeupdate();
statement = connection->createstatement();
resultset = statement->executequery("select * from new_table ");
for (;resultset->next();)
{
cout << resultset->getint("number") << " : " <<
utf8tomultibyte(resultset->getstring("wincount")) << " : " <<
utf8tomultibyte(resultset->getstring("totalgameplay")) << endl;
}
delete resultset;
delete preparedstatement;
delete connection;
}
catch (sql::sqlexception e)
{
cout << "# err: sqlexception in " << __file__;
cout << "(" << __function__ << ") on line " << __line__ << endl;
cout << "# err: " << e.what();
cout << " (mysql error code: " << e.geterrorcode();
cout << ", sqlstate: " << e.getsqlstate() << " )" << endl;
}
/*for (size_t i = 0; i < original.fd_count; ++i)
{
if (original.fd_array[i] != serversocket)
{
std::cout << original.fd_array[i] << std::endl;
int sentlength = send(original.fd_array[i], buffer, 8, 0);
}
}*/
}
}
}
}
}
closesocket(ServerSocket);
WSACleanup();
return 0;
}
std::string Utf8ToMultiByte(std::string utf8_str)
{
std::string resultString; char* pszIn = new char[utf8_str.length() + 1];
strncpy_s(pszIn, utf8_str.length() + 1, utf8_str.c_str(), utf8_str.length());
int nLenOfUni = 0, nLenOfANSI = 0; wchar_t* uni_wchar = NULL;
char* pszOut = NULL;
// 1. utf8 Length
if ((nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), NULL, 0)) <= 0)
return nullptr;
uni_wchar = new wchar_t[nLenOfUni + 1];
memset(uni_wchar, 0x00, sizeof(wchar_t) * (nLenOfUni + 1));
// 2. utf8 --> unicode
nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), uni_wchar, nLenOfUni);
// 3. ANSI(multibyte) Length
if ((nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, NULL, 0, NULL, NULL)) <= 0)
{
delete[] uni_wchar; return 0;
}
pszOut = new char[nLenOfANSI + 1];
memset(pszOut, 0x00, sizeof(char) * (nLenOfANSI + 1));
// 4. unicode --> ANSI(multibyte)
nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, pszOut, nLenOfANSI, NULL, NULL);
pszOut[nLenOfANSI] = 0;
resultString = pszOut;
delete[] uni_wchar;
delete[] pszOut;
return resultString;
}
[1]: https://sunny-green-970.notion.site/Error-ea96fbef0ea64e1bb1fd966699657547
[2]: https://i.stack.imgur.com/VK8m0.png

CryptProtectData in one exe and CryptUnprotectData in different exe on same machine and same user credentials fails - Error code 998

When both CryptProtectData and CryptUnprotectData done in same exe like below code, it works.
When we run CryptProtectData first by commentting CryptUnprotectData and then again run CryptUnprotectData by commenting CryptProtectData , the decryption fails with error code -
ERROR_NOACCESS
998 (0x3E6)
Invalid access to memory location.
#pragma once
#include <atlstr.h>
#include <string>
#include <iostream>
#include <fstream>
#include <atlbase.h>
#include <atlcom.h>
#pragma comment(lib, "crypt32.lib")
int main()
{
std::string username = "abcxyzabc";
std::string fileName = "./ConfigInfoNew.dat";
//==================Encryption=========================
bool retvalue = true;
std::ofstream encryptedfile(filename, std::ios::out | std::ios::binary);
DATA_BLOB dataout;
char* ca = new char[username.size() + 1];
std::copy(username.begin(), username.end(), ca);
ca[username.size()] = '\0';
byte* pbdatainput = (byte*)ca;
dword cbdatainput = strlen((char*)pbdatainput) + 1;
DATA_BLOB datain;
datain.pbdata = pbdatainput;
datain.cbdata = cbdatainput;
//-------------------------------------------------------------------
// begin protect phase.
if (cryptprotectdata(&datain,
null, // a description string.
null, // optional entropy not used.
null, // reserved.
null, // pass a promptstruct.
CRYPTPROTECT_LOCAL_MACHINE,//unsigned int(0),
&dataout))
{
std::cout << (char*)(dataout.pbdata) << std::endl;
encryptedfile.write((char*)&dataout.cbdata, sizeof(dword));
encryptedfile.write((char*)&dataout.pbdata, sizeof(dataout.pbdata));
dword errcode = getlasterror();
std::cout << " encrypt success code ---" + std::to_string(errcode) + "---" << std::endl;
}
else
{
dword errcode = getlasterror();
std::cout << " encrypt failed code ---" + std::to_string(errcode) + "---" << std::endl;
}
encryptedfile.close();
//===============Decryption====================
std::ifstream decryptFile(fileName, std::ios::in);
if (decryptFile.is_open())
{
{
DATA_BLOB pEncryptedData;
decryptFile.read((char*)&pEncryptedData.cbData, sizeof(DWORD));
pEncryptedData.pbData = new BYTE[pEncryptedData.cbData];
decryptFile.read((char*)&pEncryptedData.pbData, sizeof(pEncryptedData.pbData));
DATA_BLOB DataVerify;
if (CryptUnprotectData(
&pEncryptedData,
NULL,
NULL, // Optional entropy
NULL, // Reserved
NULL, // Optional PromptStruct
CRYPTPROTECT_LOCAL_MACHINE, //unsigned int(0),
&DataVerify))
{
std::cout << (char*)(DataVerify.pbData) << std::endl;
DWORD errCode = GetLastError();
std::cout << " Decrypt Success code ---" + std::to_string(errCode) + "---" << std::endl;
}
else
{
LocalFree(pEncryptedData.pbData);
LocalFree(DataVerify.pbData);
DWORD errCode = GetLastError();
std::cout << " Decrypt failed code ---" + std::to_string(errCode) + "---" << std::endl;
return false;
}
LocalFree(pEncryptedData.pbData);
LocalFree(DataVerify.pbData);
}
}
decryptFile.close();
return 0;
}
You are writing the pointer to the encrypted data into your file, instead of writing the actual encrypted data. So it makes sense why decryption works when performed in the same process as the encryption, but not in a separate process.
You need to change this:
encryptedfile.write((char*)&dataout.pbdata, sizeof(dataout.pbdata));
...
decryptFile.read((char*)&pEncryptedData.pbData, sizeof(pEncryptedData.pbData));
To this instead:
encryptedfile.write((char*)dataout.pbdata, dataout.cbdata);
...
decryptFile.read((char*)pEncryptedData.pbData, pEncryptedData.cbData);
That being said, your code can be simplified a little bit:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#pragma comment(lib, "crypt32.lib")
int main()
{
std::string username = "abcxyzabc";
std::string fileName = "./ConfigInfoNew.dat";
//==================Encryption=========================
std::ofstream encryptedfile(filename, std::ios::binary);
if (encryptedfile.is_open())
{
DATA_BLOB datain, dataout;
datain.pbdata = reinterpret_cast<BYTE*>(username.data()); // or: reinterpret_cast<BYTE*>(const_cast<char*>(username.c_str()))
datain.cbdata = username.size() + 1;
if (!CryptProtectData(&datain,
nullptr, // a description string.
nullptr, // optional entropy not used.
nullptr, // reserved.
nullptr, // pass a promptstruct.
CRYPTPROTECT_LOCAL_MACHINE,
&dataout))
{
DWORD errcode = GetLastError();
std::cout << " encrypt failed code ---" + std::to_string(errcode) + "---" << std::endl;
return 1;
}
std::cout.write(reinterpret_cast<char*>(dataout.pbdata), dataout.cbdata);
std::cout << std::endl;
if (!(encryptedfile.write(reinterpret_cast<char*>(&dataout.cbdata), sizeof(dataout.cbdata)) &&
encryptedfile.write(reinterpret_cast<char*>(dataout.pbdata), dataout.cbdata)))
{
std::cout << " failed to write to encrypted file" << std::endl;
return 1;
}
encryptedfile.close();
std::cout << " encrypt success" << std::endl;
}
else
{
std::cout << " failed to create encrypted file" << std::endl;
return 1;
}
//===============Decryption====================
std::ifstream decryptFile(fileName, std::ios::binary);
if (decryptFile.is_open())
{
DATA_BLOB EncryptedData, DataVerify;
if (!decryptFile.read(reinterpret_cast<char*>(&EncryptedData.cbData), sizeof(EncryptedData.cbData)))
{
std::cout << " failed to read from encrypted file" << std::endl;
return 1;
}
std::vector<BYTE> buffer(EncryptedData.cbData);
EncryptedData.pbData = buffer.data();
if (!decryptFile.read(reinterpret_cast<char*>(EncryptedData.pbData), EncryptedData.cbData))
{
std::cout << " failed to read from encrypted file" << std::endl;
return 1;
}
if (!CryptUnprotectData(
&EncryptedData,
nullptr,
nullptr, // Optional entropy
nullptr, // Reserved
nullptr, // Optional PromptStruct
CRYPTPROTECT_LOCAL_MACHINE,
&DataVerify))
{
DWORD errCode = GetLastError();
std::cout << " Decrypt failed code ---" + std::to_string(errCode) + "---" << std::endl;
return 1;
}
std::cout.write(reinterpret_cast<char*>(DataVerify.pbData), DataVerify.cbData);
std::cout << std::endl;
std::cout << " decrypt success" << std::endl;
LocalFree(DataVerify.pbData);
decryptFile.close();
}
else
{
std::cout << " failed to open encrypted file" << std::endl;
return 1;
}
return 0;
}

QueryChangesVirtualDisk is returning ERROR_INVALID_HANDLE(6) even though OpenVirtualDisk is succesfull

I am trying out VirtualDisk APIs,
So far I am able to Open a VHDX file, get some of the properties by using GetVirtualDiskInformation.
But I am not able to get RCT information and ChangedAreas.
The first call to GetVirtualDiskInformation is successful.
The second call to GetVirtualDiskInformation fails with insufficient buffer ERROR_INSUFFICIENT_BUFFER(122).
Call to QueryChangesVirtualDisk fails with ERROR_INVALID_HANDLE(6).
The RCT ID hardcoded in the code is proper, I am able to get the ChangedAreas using WMI Explorer.
Attached screenshot of the same.
If it is invalid handle, then GetVirtualDiskInformation should also throw the same error?
#include "pch.h"
#include <iostream>
#include <string>
#include <cstdlib>
#define WINVER _WIN32_WINNT_WIN10
#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>
#include <initguid.h>
#pragma comment(lib, "virtdisk.lib")
DEFINE_GUID(VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT, 0xec984aec, 0xa0f9, 0x47e9, 0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b);
DEFINE_GUID(VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
int main()
{
HANDLE vhdHandle;
_VIRTUAL_STORAGE_TYPE storageType;
storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;
wchar_t path[] = L"C:\\Hyper-V\\Virtual Hard Disks\\Lacazette\\Windows2016.vhdx";
VIRTUAL_DISK_ACCESS_MASK mask = VIRTUAL_DISK_ACCESS_GET_INFO;
PGET_VIRTUAL_DISK_INFO diskInfo;
ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);
std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
if (diskInfo == NULL)
{
std::cout << "Failed to malloc disk info, ret=" << std::endl;
return 0;
}
std::wcout << "Opening Virtual disk " << path << std::endl;
DWORD res = OpenVirtualDisk(&storageType, path,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
NULL,
&vhdHandle);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to open disk, ret=" << res << std::endl;
return 0;
}
diskInfo->Version = GET_VIRTUAL_DISK_INFO_SIZE;
res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to GET_VIRTUAL_DISK_INFO_SIZE, ret=" << res << std::endl;
}
long physicalSize = diskInfo->Size.PhysicalSize;
long virtualSize = diskInfo->Size.VirtualSize;
long sectorSize = diskInfo->Size.SectorSize;
long blockSize = diskInfo->Size.BlockSize;
std::wcout << "physicalSize :" << physicalSize << std::endl;
std::wcout << "virtualSize :" << virtualSize << std::endl;
std::wcout << "sectorSize :" << sectorSize << std::endl;
std::wcout << "blockSize :" << blockSize << std::endl;
diskInfo->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE, ret=" << res << std::endl;
}
std::cout << "\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;
std::cout << "\nQuerying for changed disk areas...\n" << std::endl;
wchar_t rctId[] = L"rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001";
ULONG64 byteOffset = 0L;
ULONG64 byteLength = 19327352832;
QUERY_CHANGES_VIRTUAL_DISK_RANGE* changedAreas = NULL;
ULONG rangeCount = 0L;
ULONG64 processedLength = 0L;
res = QueryChangesVirtualDisk(&vhdHandle, rctId, byteOffset, byteLength,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
changedAreas, &rangeCount, &processedLength);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to get chanegd areas, ret=" << res << std::endl;
if (vhdHandle != NULL)
{
CloseHandle(vhdHandle);
std::cout << "closing handle!" <<std::endl;
}
return 0;
}
std::cout << "Total changed areas:" << rangeCount << std::endl;
std::cout << "Total processed length:" << processedLength << std::endl;
if (vhdHandle != NULL)
{
CloseHandle(vhdHandle);
}
return 0;
}
Output of the program:
Screenshot of wmi explorer output.
Here's something that more or less works.. the issue was with the format of the rctid which I was passing to the QueryChangesVirtualDisk API. Should be as in the below sample. I was enclosing it inside the braces {} which was not correct. The below code returns RCT changed blocks successfully
Another observation is that it seems the ChangeTrackingState.MostRecentId which we get from GetVirtualDiskInformation for a offline vhdx is one more than what we initially created while the VM was up.. For example, I created a reference point with rctid: rctX:4abdf273:7e45:4748:85af:78ec4af82ebf:00000000 Now when the vhdx is offline and if I query the ChangeTrackingState.MostRecentId it is giving me this : rctX:4abdf273:7e45:4748:85af:78ec4af82ebf:00000001 which fails the QueryChangesVirtualDisk with invalid rctid error. The below function expects the user to pass the correct rctid externally. Apparently, the Get-VmReferencePoints still lists only the earlier 00000 reference point.. This one (00001) seems to be returned only by the GetVirtualDiskInformation API
Finally, for the other issue of getting access denied with a live VM, it seems we have to set the VIRTUAL_DISK_ACCESS_MASK in OpenVirtualDisk to 0 along with version 3 of OPEN_VIRTUAL_DISK_PARAMETERS as shown below. With this we we are able to query RCT CBT from a live checkpointed VM's base disk. Got clarified from https://github.com/cloudbase/rct-service/issues/1
#include <windows.h>
#include <virtdisk.h>
#include <iostream>
bool QueryRCTData(const std::wstring& file, const std::wstring& rctid)
{
DWORD fRet;
HANDLE hVHD;
VIRTUAL_STORAGE_TYPE vst =
{
VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN,
{0xEC984AEC, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B }}
};
OPEN_VIRTUAL_DISK_PARAMETERS params = { 0 };
params.Version = OPEN_VIRTUAL_DISK_VERSION_3;
DWORD fRet = OpenVirtualDisk(
&vst,
file.c_str(),
(VIRTUAL_DISK_ACCESS_MASK) 0, //VIRTUAL_DISK_ACCESS_ALL, //VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
&params,
&hvhd);
if (fRet != ERROR_SUCCESS)
{
std::cout << "OpenVirtualDisk failed " << fRet << "\n";
return false;
}
//query rctid
WCHAR vdinfo[2048];
ZeroMemory(vdinfo, sizeof(vdinfo));
((GET_VIRTUAL_DISK_INFO *)vdinfo)->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
ULONG vdinfoSize = sizeof(vdinfo);
fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)vdinfo,
NULL);
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE failed " << fRet << "\n";
return false;
}
std::wcout << "RCT ID : " << std::wstring(((GET_VIRTUAL_DISK_INFO *)vdinfo)->ChangeTrackingState.MostRecentId) << "\n";
//query disk length
ZeroMemory(vdinfo, sizeof(vdinfo));
((GET_VIRTUAL_DISK_INFO *)vdinfo)->Version = GET_VIRTUAL_DISK_INFO_SIZE;
vdinfoSize = sizeof(vdinfo);
fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)vdinfo,
NULL);
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_SIZE failed " << fRet << "\n";
return false;
}
std::cout << "Disk length : " << ((GET_VIRTUAL_DISK_INFO *)vdinfo)->Size.VirtualSize << "\n";
ULONG RangeCount = 1024;
ULONG64 ProcessedLength = 0;
QUERY_CHANGES_VIRTUAL_DISK_RANGE Ranges[1024] = { 0 };
fRet = QueryChangesVirtualDisk(
hVHD,
rctid.c_str(), //((GET_VIRTUAL_DISK_INFO *)vdinfo)->ChangeTrackingState.MostRecentId,
0,
((GET_VIRTUAL_DISK_INFO *)vdinfo)->Size.VirtualSize,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
Ranges,
&RangeCount,
&ProcessedLength);
if (fRet != ERROR_SUCCESS)
{
std::cout << "QueryChangesVirtualDisk failed " << fRet << "\n";
return false;
}
std::cout << "RangeCount : " << RangeCount << "\n";
std::cout << "ProcessedLength : " << ProcessedLength << "\n";
for (int i = 0; i < RangeCount; i++)
{
std::cout << "Range offset : " << Ranges[i].ByteOffset << "\n";
std::cout << "Range length : " << Ranges[i].ByteLength << "\n";
}
CloseHandle(hVHD);
return true;
}
int main(void)
{
QueryRCTData(L"D:\\BACKUP\\INCR\\Virtual Hard Disks\\2019.vhdx", L"rctX:4abdf273:7e45:4748:85af:78ec4af82ebf:00000000");
return 0;
}
#pragma comment(lib, "virtdisk.lib")
Here is my working code for getting changed blocks from offline VHDX.
(most credit goes to Neelabh Mam who posted above)
Hope it might help someone struggling to make RCT work with C++.
BOOLEAN VHDWRAP_CONVENTION CloseVhd(HANDLE hDisk)
{
return CloseHandle(hDisk) == TRUE;
}
HANDLE VHDWRAP_CONVENTION OpenVhdx(PCWSTR path, unsigned mask)
{
DWORD fRet;
HANDLE hVHD;
VIRTUAL_STORAGE_TYPE vst =
{
VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN,
{0xEC984AEC, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B }}
};
OPEN_VIRTUAL_DISK_PARAMETERS params = { 0 };
params.Version = OPEN_VIRTUAL_DISK_VERSION_3;
fRet = OpenVirtualDisk(
&vst,
path, (VIRTUAL_DISK_ACCESS_MASK)mask,
OPEN_VIRTUAL_DISK_FLAG_NONE,
&params,
&hVHD);
g_dwLastError = fRet;
return hVHD;
}
VHDWRAP_API BOOLEAN VHDWRAP_CONVENTION EnableVhdRct(HANDLE hVHD)
{
SET_VIRTUAL_DISK_INFO vdinfo;
vdinfo.Version = SET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
vdinfo.ChangeTrackingEnabled = TRUE;
DWORD fRet = SetVirtualDiskInformation(hVHD, &vdinfo);
g_dwLastError = fRet;
return fRet == 0;
}
VHDWRAP_API BOOLEAN VHDWRAP_CONVENTION DisableVhdRct(HANDLE hVHD)
{
SET_VIRTUAL_DISK_INFO vdinfo;
vdinfo.Version = SET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
vdinfo.ChangeTrackingEnabled = FALSE;
DWORD fRet = SetVirtualDiskInformation(hVHD, &vdinfo);
g_dwLastError = fRet;
return fRet == 0;
}
VHDWRAP_API BOOLEAN VHDWRAP_CONVENTION QueryVhdRct(HANDLE hVHD, LPCWSTR szRctId)
{
//query rctid
WCHAR vdinfo[1024];
ZeroMemory(vdinfo, sizeof(vdinfo));
((GET_VIRTUAL_DISK_INFO*)vdinfo)->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
ULONG vdinfoSize = sizeof(vdinfo);
DWORD fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)vdinfo,
NULL);
g_dwLastError = fRet;
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE failed " << fRet << "\n";
return false;
}
std::wcout << L"RCT status : " << ((((GET_VIRTUAL_DISK_INFO*)vdinfo)->ChangeTrackingState.Enabled) ? L"enabled" : L"disabled") << L"\n";
std::wcout << L"RCT ID : " << std::wstring(((GET_VIRTUAL_DISK_INFO*)vdinfo)->ChangeTrackingState.MostRecentId) << "\n";
std::wcout << L"RCT changes : " << ((((GET_VIRTUAL_DISK_INFO*)vdinfo)->ChangeTrackingState.NewerChanges) ? L"yes": L"no") << "\n";
//query disk length
_GET_VIRTUAL_DISK_INFO sizeInfo;
sizeInfo.Version = GET_VIRTUAL_DISK_INFO_SIZE;
vdinfoSize = sizeof(sizeInfo);
fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)&sizeInfo,
NULL);
g_dwLastError = fRet;
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_SIZE failed " << fRet << "\n";
return FALSE;
}
std::cout << "Disk length : " << sizeInfo.Size.VirtualSize << "\n";
const ULONG MaxRangeCount = 4096*1024;
ULONG RangeCount = MaxRangeCount;
ULONG64 ProcessedLength = 0;
QUERY_CHANGES_VIRTUAL_DISK_RANGE* Ranges = new QUERY_CHANGES_VIRTUAL_DISK_RANGE[MaxRangeCount];
fRet = QueryChangesVirtualDisk(
hVHD,
szRctId?szRctId : ((GET_VIRTUAL_DISK_INFO *)vdinfo)->ChangeTrackingState.MostRecentId,
0,
sizeInfo.Size.VirtualSize,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
Ranges,
&RangeCount,
&ProcessedLength);
g_dwLastError = fRet;
if (fRet != ERROR_SUCCESS)
{
delete[] Ranges;
std::cout << "QueryChangesVirtualDisk failed " << fRet << " ranges:" << RangeCount << " len " << ProcessedLength << "\n";
return FALSE;
}
if (MaxRangeCount <= RangeCount || ProcessedLength < sizeInfo.Size.VirtualSize)
{
delete[] Ranges;
std::cout << "Not enough resources to capture all the changes \n";
return FALSE;
}
std::cout << "RangeCount : " << RangeCount << "\n";
std::cout << "ProcessedLength : " << ProcessedLength << "\n";
for (int i = 0; i < RangeCount; i++)
{
std::cout << "Range offset : " << Ranges[i].ByteOffset << "\n";
std::cout << "Range length : " << Ranges[i].ByteLength << "\n";
}
delete[] Ranges;
return TRUE;
}

How to send OID_PM_WOL_PATTERN_LIST to NDIS driver in C++?

I would like to query the Wake On Lan patterns defined on an Ethernet card in C++ (later on I would like to upload such patterns, but one step at once. :) ). As I understood I have to send the OID_PM_WOL_PATTERN_LIST request from the user space to the kernel space. I found that on Windows this kind of requests can be sent calling the DeviceIoControl. I used >this< example code as a starting point. I have the GUID of the device and I can issue some basic IOCTL_* commands.
If I understood well, I have to issue a specific IOCTL_* command with the InBuffer pointing with some structure (maybe NDIS_OID_REQUEST) filled with OID_PM_WOL_PATTERN_LIST command.
I tried to find some example how this should be done, but I was not able to find a proper one.
Could someone help how this should be done? Or an example source would be helpful.
Finally I have found the solution...
#include <iostream>
#include <winsock2.h> /* Prevent inclusion of winsock.h in windows.h */
#include <iphlpapi.h>
#include <Windows.h>
#include <IPTypes.h>
#include <WinIoCtl.h>
#define UM_NDIS650
#include <NtDDNdis.h>
#include <strsafe.h>
#pragma comment(lib, "iphlpapi.lib")
//#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define ErrorMsgPos() errorMsg(__FILE__, __LINE__, __func__)
DWORD errorMsg(const char *strFile, DWORD line, const char *strFunc) {
// Retrieve the system error message for the last-error code
std::wstringstream ss;
ss << strFile << ':' << line << ' ' << strFunc << "();";
wstring str = ss.str();
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dwErr = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL
);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + str.length() + 40) * sizeof(TCHAR)
);
if (lpDisplayBuf) {
StringCchPrintfW(
(LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s\nfailed with: [%d] \"%s\""),
str.c_str(),
dwErr,
(LPTSTR)lpMsgBuf
);
wcerr << (LPCTSTR)lpDisplayBuf << endl;
//MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
}
LocalFree(lpDisplayBuf);
LocalFree(lpMsgBuf);
//ExitProcess(dw);
return dwErr;
} // errorMsg
void outData(DWORD dw, char *data) {
DWORD i;
char buf[17];
memset(buf, 0, 17);
char prev = cout.fill('0');
for (i = 0; i < dw; ++i) {
cout << hex;
if (i % 16 == 0) {
char prev = cout.fill('0');
cout << " " << setw(4) << (DWORD)i << " : ";
cout.fill(prev);
memset(buf, 0, 16);
}
cout << setw(2) << ((unsigned int)data[i] & 0xFF);
buf[i % 16] = (unsigned int)(data[i] == 0 ? '_'
: data[i] < 32 || data[i] > 127 ? '.' : data[i]
) & 0xff;
if (i % 16 < 15) cout << (i % 4 == 3 ? " " : " ");
else cout << " : " << buf << dec << endl;
}
// Final, partial row
for (int i = dw % 16 == 0 ? 16 : dw % 16; i < 16; ++i) {
cout << " ";
if (i % 16 < 15) cout << (i % 4 == 3 ? " " : " ");
else cout << " : " << buf << endl;
}
cout.fill(prev);
} // outData
#define ShowGlobalStat(h, cd, buf,size, rv_sz) \
showGlobalStat(h, cd, #cd, buf, size, rv_sz, __FILE__, __LINE__, __func__)
DWORD showGlobalStat(HANDLE hDevice, unsigned int cd, const char* name
, char *outBuf, size_t size, size_t *rv_size
, const char* file, unsigned int line, const char* func
) {
unsigned int code = cd;
DWORD dwBytesReturned;
BOOL res = DeviceIoControl(
hDevice, IOCTL_NDIS_QUERY_GLOBAL_STATS,
&code, sizeof(code),
outBuf, size,
&dwBytesReturned, NULL
);
char prev = cout.fill('0');
cout << "\n*** cmd: " << name << ", code: " << hex << setw(8) << cd;
DWORD dw = 0;
*rv_size = dwBytesReturned;
if (res) {
cout << " bytes(" << dwBytesReturned << ")" << dec << endl;
cout.fill(prev);
outData(dwBytesReturned, outBuf);
} else {
cout << endl;
dw = errorMsg(file, line, func);
}
return dw;
} // showGlobalStat
int main() {
char buf[2048];
size_t sz = sizeof(buf), rw;
ShowGlobalStat(hDevice, OID_PM_WOL_PATTERN_LIST, buf, sz, &rw);
if (rw) {
ULONG offset = 0;
do {
NDIS_PM_WOL_PATTERN* pBuf =
(NDIS_PM_WOL_PATTERN*)(buf + offset);
cout << "Offset: << offset << endl;
offset = pBuf->NextWoLPatternOffset;
} while (offset > 0);
} else
cout << "... No items. Size of NDIS_PM_WOL_PATTERN "
<< sizeof(NDIS_PM_WOL_PATTERN) << endl;
} // main

Server - Client RSA keypair exchange

I'm new to programming and i've got this little project going for my diploma and i need help on this little code. This is a Server->Client C++ code where server generates and sends RSA Keypair to client. My problem is that both server and client codes compiled without any problem but when i start it the client side doesn't get any keypair just blank.
Here is my server code:
#include <iostream>
#include <cstdlib>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <stdio.h>
#include <string.h>
#define KEY_LENGTH 1024
#define PUB_EXP 3
#define PRINT_KEYS
#define WRITE_TO_FILE
using std::exit;
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
void handle_error(const char* file, int lineno, const char* msg)
{
std::cerr << "\n** " << file << ":" << lineno << " " << msg << "\n";
ERR_print_errors_fp(stderr);
exit(-1);
}
void init_OpenSSL()
{
std::cout << "Initializng OpenSSL library ... ";
if (!SSL_library_init())
int_error("OpenSSL initialization failed");
std::cout << "done\n";
SSL_load_error_strings();
}
DH* setup_dh()
{
DH* dh = DH_new();
if (!dh)
int_error("DH_new failed");
std::cout << "Generating DH parameters ... ";
if (!DH_generate_parameters_ex(dh, 2, DH_GENERATOR_2, 0))
int_error("DH_generate_parameters_ex failed");
std::cout << "done\n";
std::cout << "Checking DH parameters ... ";
int codes = 0;
if (!DH_check(dh, &codes))
int_error("DH_check failed");
std::cout << "done\n";
std::cout << "Generating DH keys ... ";
if (!DH_generate_key(dh))
int_error("DH_generate_key failed");
std::cout << "done\n";
return dh;
}
SSL_CTX* setup_ctx()
{
SSL_CTX* ctx;
std::cout << "Creating context ... ";
ctx = SSL_CTX_new(TLSv1_server_method());
if (!ctx)
int_error("SSL_CTX_new failed");
std::cout << "done\n";
DH* dh = setup_dh();
std::cout << "Setting DH parameters ... ";
SSL_CTX_set_tmp_dh(ctx, dh);
std::cout << "done\n";
std::cout << "Setting cipher list ... ";
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA") != 1)
int_error("Error setting cipher list (no valid ciphers)");
std::cout << "done\n";
return ctx;
}
int main()
{
init_OpenSSL();
BIO *acc, *client;
SSL* ssl;
SSL_CTX* ctx;
ctx = setup_ctx();
size_t pri_len;
size_t pub_len;
char *pri_key;
char *pub_key;
std::cout << "Generating RSA (%d bits) keypair...\n", 1024;
RSA *keypair = RSA_generate_key(1024, 3, NULL, NULL);
BIO *pri = BIO_new(BIO_s_mem());
BIO *pub = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_RSAPublicKey(pub, keypair);
pri_len = BIO_pending(pri);
pub_len = BIO_pending(pub);
pri_key = (char*)malloc(pri_len + 1);
pub_key = (char*)malloc(pub_len + 1);
BIO_read(pri, pri_key, pri_len);
BIO_read(pub, pub_key, pub_len);
pri_key[pri_len] = '\0';
pub_key[pub_len] = '\0';
std::cout << "Creating server socket ... ";
acc = BIO_new_accept("*:5055");
if (!acc)
int_error("Error creating server socket");
std::cout << "done\n";
std::cout << "Binding server socket ... ";
if (BIO_do_accept(acc) <= 0)
int_error("Error binding server socket");
std::cout << "done\n";
while (true) {
std::cout << "Accepting connections ...\n";
if (BIO_do_accept(acc) <= 0)
int_error("Error accepting connection");
client = BIO_pop(acc);
std::cout << "Creating context ... ";
if (!(ssl = SSL_new(ctx)))
int_error("Error creating SSL context");
std::cout << "done\n";
SSL_set_bio(ssl, client, client);
if (SSL_accept(ssl) <= 0)
int_error("Error accepting SSL connection");
std::cout << "SSL connection opened: " << SSL_get_cipher(ssl) << " " <<
SSL_get_cipher_version(ssl) << " (" << SSL_get_cipher_bits(ssl, 0) << " bits)\n";
char buff[256] = {0};
int r = SSL_read(ssl, buff, sizeof buff);
if (r > 0) {
std::cout << buff;
SSL_write(ssl, keypair, 1024 );
}
SSL_shutdown(ssl);
SSL_free(ssl);
std::cout << "SSL connection finished\n";
}
SSL_CTX_free(ctx);
BIO_free(acc);
std::cout << "Server closed\n";
}
Here is my client code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <openssl/ssl.h>
#include <openssl/err.h>
using namespace std;
using std::exit;
#define int_error(msg) handle_error(__FILE__, __LINE__, msg)
void handle_error(const char* file, int lineno, const char* msg)
{
std::cerr << "** " << file << ":" << lineno << " " << msg << "\n";
ERR_print_errors_fp(stderr);
exit(-1);
}
void init_OpenSSL()
{
std::cout << "Initializng OpenSSL library ... ";
if (!SSL_library_init())
int_error("OpenSSL initialization failed");
std::cout << "done\n";
SSL_load_error_strings();
}
SSL_CTX* setup_ctx()
{
SSL_CTX* ctx;
std::cout << "Creating context ... ";
ctx = SSL_CTX_new(TLSv1_client_method());
if (!ctx)
int_error("SSL_CTX_new failed");
std::cout << "done\n";
std::cout << "Setting cipher list ... ";
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA") != 1)
int_error("Error setting cipher list (no valid ciphers)");
std::cout << "done\n";
return ctx;
}
int main()
{
init_OpenSSL();
BIO* conn;
SSL* ssl;
SSL_CTX* ctx;
ofstream myfile;
ctx = setup_ctx();
std::cout << "Creating connection ... ";
conn = BIO_new_connect("192.168.1.10:5055");
if (!conn)
int_error("Error creating connection");
std::cout << "done\n";
std::cout << "Connecting to server ... ";
if (BIO_do_connect(conn) <= 0)
int_error("Error connecting to server");
std::cout << "done\n";
std::cout << "Creating context ... ";
if (!(ssl = SSL_new(ctx)))
int_error("Error creating an SSL context");
std::cout << "done\n";
SSL_set_bio(ssl, conn, conn);
std::cout << "Opening connection ... ";
if (SSL_connect(ssl) <= 0)
int_error("Error connecting SSL object");
std::cout << "done\n";
SSL_write(ssl, "The client is connected", 26);
char buff[64] = {0};
int bread = SSL_read(ssl, buff, sizeof buff);
if (bread > 0)
std::cout << "The key has been recieved\n";
myfile.open ("keypair.pem");
myfile << buff;
myfile.close();
SSL_shutdown(ssl);
SSL_free(ssl);
std::cout << "SSL connection finished\n";
SSL_CTX_free(ctx);
std::cout << "Client finished\n";
}
Can someone show me what i did wrong and it would be great if someone can tell me how i can get my private key and public keys(server generated) separately. Thanks a lot guys...really appreciate it