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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage