I am trying to read a x509 certificate using openssl CLI through C++. (Yes I know that OpenSSL has also a C API, but that is not important for my question). OpenSSL version is 1.1.0g and gcc compiler is 7.4.0
So, I want to execute the command openssl x509 -noout -text -in certFile.cer
and get the output.
I tried to use three different C++ solutions:
popen()
, to retrieve the outputsystem()
, adding at the end of the command > temp.txt
to redirect the output and then reading from itsystem()
, using the command openssl x509 -noout -text -in certFile.cer -out tempFile
so that I do not need to redirect the output, but the output is written to a file. Then, I read the file.This is a piece of the code that I am using (as you can see, I also tried to add stdbuf -o 0
to avoid buffering)
string execCommandAndGetOutput_withPopen(const char* cmd, int* result)
{
std::array<char, 1024> buffer;
std::string output;
string cmd_unbuf;
cmd_unbuf.append("stdbuf -o 0 ");
cmd_unbuf.append(cmd);
cmd_unbuf.append(" 2>&1");
FILE* pipe = popen(cmd_unbuf.c_str(), "r");
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
output += buffer.data();
}
*result = pclose(pipe);
return output;
}
string execCommandAndGetOutput_withSystem(const char* cmd, int* result)
{
std::string output;
string cmd_unbuf;
cmd_unbuf.append("stdbuf -o 0 ");
cmd_unbuf.append(cmd);
cmd_unbuf.append(" > /tmp/temp 2>&1");
int cmdResult = system(cmd_unbuf.c_str());
std::ifstream file("/tmp/temp");
std::string fileContent((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
remove("/tmp/temp");
*result = cmdResult;
return fileContent;
}
When using the second function, I tried to NOT remove the temporary file, and check its content, and the content is complete. So it is not a problem in the system()
call.
In all cases, the string that I get is NOT complete. In particular it stops always at the same point, in particular in the middle of a URL, just before %2CO
. But AFAIK, this should not be a problem, %2
should be just a coma, html-encoded.
I tried to check the string size, and the string that I get has size 4262
, that should be far away from its maximum.
I also tried it in two machines: the first machine where I get the problem, is were all my program is installed, and where I get the error. In the second machine, my development machine, I just run some tests while developing, and I never noticed this problem, with the same input. Note that both machines are Ubuntu server 18.04.3.
So my ideas were:
%2
is a strange character, but it seems notstring
is too big, but it seems notI am out of ideas...someone has some suggestion? Some particular C library to check? Other ideas?
Edit:
Even if I would not post the certificate affected, I can post the line affected. This is the complete line:
URI:ldap://directory.swisssign.net/CN=DA32F949F851CC9871660CD9CEB6DB923F094BEF%2CO=SwissSign%2CC=CH?certificateRevocationList?base?objectClass=cRLDistributionPoint
But I get only:
URI:ldap://directory.swisssign.net/CN=DA32F949F851CC9871660CD9CEB6DB923F094BEF
I tried also adding | grep -A 10 'X509v3 CRL Distribution Points:'
to the command (so that I could exclude that the problem was the length of the string), and the output is the same, the string is truncated. So it seems the problem is related to the character %2C
somehow.
Any idea?
Edit 2:
Change subject
Edit 3:
I was debugging an error, that was why I was printing the string....unfortunately I used syslog()
to print it... I suppose 2%C
was interpreted as format
If %2C
in a string gives problem, make sure you are not using some function that use format
, such as printf
or syslog
In my case, while I was debugging an error, I was printing the string containing "%2C" using syslog
and that made the confusion...