Wie man das PKCS7_sign-Ergebnis in ein char * oder std :: string @ brin
Ich versuche, einen kleinen Mail-Milter zu schreiben, um Mails mit S / MIME zu signieren. Bisher habe ich den Code bis zum Signieren der Mail vervollständigt. Ich habe die Demo / Smime-Codebeispiele in openssl verwendet, um den Job zu erledigen. Leider zeigen die Beispiele, wie eine Eingabenachricht in eine Ausgabedatei geschrieben wird, aber ich benötige das Ergebnis als Zeichenfolge.
Dies ist meine Smime-Methode:
void Smime::sign() {
if (!isLoaded())
return;
// Null-mailer or unknown
if (mailFrom.empty())
return;
auto *client = util::mlfipriv(ctx);
bool signedOrEncrypted = false;
std::vector<std::string> contentType;
contentType.push_back("multipart/signed");
contentType.push_back("multipart/encrypted");
contentType.push_back("application/pkcs7-mime");
if (client->sessionData.count("Content-Type") == 1) {
std::string value {client->sessionData["Content-Type"]};
std::size_t found;
for (int i=0; i<contentType.size(); i++) {
found = value.find(contentType.at(i));
if (found != std::string::npos) {
signedOrEncrypted = true;
break;
}
}
}
if (signedOrEncrypted) {
const char logmsg[] = "Message already signed or encrypted";
syslog(LOG_NOTICE, "%s", logmsg);
return;
}
/*
* TODO:
* Catch more cases, where an email already could have been encrypted
* or signed elsewhere.
*/
mapfile::Map email {mailFrom};
auto cert = fs::path(email.getSmimeFilename<mapfile::Smime::CERT>());
auto key = fs::path(email.getSmimeFilename<mapfile::Smime::KEY>());
if (!fs::exists(cert) && !fs::is_regular(cert))
return;
if (!fs::exists(key) && !fs::is_regular(key))
return;
// Signing starts here
BIO *in = nullptr, *out = nullptr, *tbio = nullptr;
X509 *scert = nullptr;
EVP_PKEY *skey = nullptr;
PKCS7 *p7 = nullptr;
int flags = PKCS7_DETACHED | PKCS7_STREAM;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
// S/MIME certificate
tbio = BIO_new_file(cert.string().c_str(), "r");
if (!tbio) {
std::cerr << "Error: BIO_new_file(Cert) failed" << std::endl;
return;
}
scert = PEM_read_bio_X509(tbio, nullptr, 0, nullptr);
// S/MIME key
tbio = BIO_new_file(key.string().c_str(), "r");
if (!tbio) {
std::cerr << "Error: BIO_new_file(Key) failed" << std::endl;
return;
}
skey = PEM_read_bio_PrivateKey(tbio, nullptr, 0, nullptr);
if (!scert || !skey) {
std::cerr << "Error: Neither cert or key was loaded" << std::endl;
return;
}
// Loading mail content from temp file
in = BIO_new_file(client->getTempFile().c_str(), "r");
if (!in) {
std::cerr << "Error: Unable to load content from temp file"
<< std::endl;
return;
}
// Signing
p7 = PKCS7_sign(scert, skey, nullptr, in, flags);
if (!p7) {
std::cerr << "Error: Message could not be signed" << std::endl;
return;
}
// Cleanup
PKCS7_free(p7);
X509_free(scert);
EVP_PKEY_free(skey);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
smimeSigned = true;
}
Da es mehr als 1600 Manpages für openssl gibt, habe ich keine Ahnung, wo ich nach Informationen suchen soll.
Ich würde gerne das "p7" verwenden und es in einen einfachen std :: string schreiben (oder char *, falls erforderlich). Die Milter-Anwendung, die ich schreibe, nimmt diesen String auf und führt einen Change-Body aus (noch nicht geschrieben, aber das ist meine Idee).
Kann mich jemand auf Routinen / Manpages verweisen oder hat er ein Codebeispiel, das mir helfen könnte?
Danke im Vorau