Просто прочитайте мой ответ напрямую, игнорируйте следующий текст ...
Я пытаюсь прочитать сертификат x509, используя CLI openssl через C ++. (Да, я знаю, что OpenSSL также имеет C API, но это не важно для моего вопроса). Версия OpenSSL - 1.1.0g, а компилятор gcc - 7.4.0
Итак, я хочу выполнить команду openssl x509 -noout -text -in certFile.cer
и получить вывод.
Я пытался использовать три различных решения C ++:
popen()
, для получения выходных данных system()
, добавление в конце команды > temp.txt
для перенаправления вывода и затем чтение из него system()
, используя команду openssl x509 -noout -text -in certFile.cer -out tempFile
, так что мне не нужно перенаправлять вывод, но вывод записывается в файл. Затем я читаю файл.
Это фрагмент кода, который я использую (как вы можете видеть, я также пытался добавить stdbuf -o 0
, чтобы избежать буферизации)
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;
}
При использовании второй функции я попытался НЕ удалить временный файл, проверить его содержимое, и содержимое завершено. Так что это не проблема при вызове system()
.
Во всех случаях полученная мной строка НЕ завершена. В частности, он всегда останавливается в одной и той же точке, в частности, в середине URL, перед %2CO
. Но AFAIK, это не должно быть проблемой, %2
должно быть просто комой, закодированной в html.
Я попытался проверить размер строки, и полученная строка имеет размер 4262
, чтодолжно быть далеко от его максимума.
Я также попробовал его на двух машинах: первая машина, на которой я обнаружил проблему, - это все мои программы, и где я получаю ошибку. На второй машине, моей машине для разработки, я просто запускал несколько тестов во время разработки и никогда не замечал этой проблемы с тем же вводом. Обратите внимание, что обе машины являются сервером Ubuntu 18.04.3.
Так что мои идеи были такими:
%2
- странный символ, но, похоже, не string
слишком большой, но, кажется, не - машины разные ... да, может быть, что какой-то пакет отличается, но библиотеки C ++ должны быть одинаковыми ... Я не 100% уверен, но насколько я проверял, они ...
У меня нет идей ... у кого-то есть какие-то предложения? Какую-то конкретную библиотеку C для проверки? Другие идеи?
Редактировать:
Даже если я не отправлю затронутый сертификат, я могу опубликовать затронутую строку. Это полная строка:
URI:ldap://directory.swisssign.net/CN=DA32F949F851CC9871660CD9CEB6DB923F094BEF%2CO=SwissSign%2CC=CH?certificateRevocationList?base?objectClass=cRLDistributionPoint
Но я получаю только:
URI:ldap://directory.swisssign.net/CN=DA32F949F851CC9871660CD9CEB6DB923F094BEF
Я также попытался добавить | grep -A 10 'X509v3 CRL Distribution Points:'
в команду (чтобы исключить, что проблема заключалась вдлина строки), а на выходе то же самое, строка усекается. Похоже, проблема связана с каким-то персонажем %2C
.
Есть идеи?
Изменить 2:
Изменить тему
Редактировать 3:
Я отлаживал ошибку, поэтому печатал строку ... к сожалению, я использовал syslog()
для ее печати ... Полагаю,2%C
было интерпретировано как format