#include "wvfile.h" #define private public #include "wvocsp.h" #include "wvtest.h" #include "wvx509mgr.h" #undef private #include "wvfileutils.h" #include "wvrsa.h" #include "wvsystem.h" // default keylen for where we're not using pre-existing certs const static int DEFAULT_KEYLEN = 512; // for objects with only one kind of encoding (e.g. ocsp requests/replies) #define ENCODE_TO_FILE(FNAME, OBJ) \ { \ WvDynBuf buf; \ OBJ.encode(buf); \ WvFile f(FNAME, O_CREAT|O_WRONLY); \ f.write(buf); \ } // for objects with multiple encodings (e.g. certs) #define ENCODE_TO_FILE2(FNAME, OBJ, FORMAT) \ { \ WvDynBuf buf; \ OBJ.encode(FORMAT, buf); \ WvFile f(FNAME, O_CREAT|O_WRONLY); \ f.write(buf); \ } // dumping some stuff to file #define DUMP_TO_FILE(FNAME, STUFF) \ { \ WvFile f(FNAME, O_CREAT|O_WRONLY); \ f.print(STUFF); \ } static WvOCSPResp::Status test_ocsp_req(WvX509 &cert, WvX509Mgr &cacert, WvX509Mgr &ocspcert, WvStringParm indexcontents) { WvString reqfname = wvtmpfilename("ocspreq"); WvString respfname = wvtmpfilename("ocspresp"); WvString indexfname = wvtmpfilename("ocspidx"); WvString cafname = wvtmpfilename("ocspca"); WvString cakeyfname = wvtmpfilename("ocspcakey"); WvString ocspfname = wvtmpfilename("ocspresp"); WvString ocspkeyfname = wvtmpfilename("ocsprespkey"); WvString clifname = wvtmpfilename("ocspcli"); ENCODE_TO_FILE2(clifname, cert, WvX509::CertPEM); ENCODE_TO_FILE2(cafname, cacert, WvX509::CertPEM); ENCODE_TO_FILE2(ocspfname, ocspcert, WvX509::CertPEM); ENCODE_TO_FILE2(cakeyfname, cacert, WvRSAKey::RsaPEM); ENCODE_TO_FILE2(ocspkeyfname, ocspcert, WvRSAKey::RsaPEM); DUMP_TO_FILE(indexfname, indexcontents); WvOCSPReq req(cert, cacert); ENCODE_TO_FILE(reqfname, req); WvSystem("openssl", "ocsp", "-CAfile", cafname, "-index", indexfname, "-rsigner", ocspfname, "-rkey", ocspkeyfname, "-CA", cafname, "-reqin", reqfname, "-respout", respfname); WvOCSPResp resp; { WvFile f(respfname, O_RDONLY); WvDynBuf buf; while (f.isok()) f.read(buf, 1024); resp.decode(buf); } if (WVPASS(resp.isok())) { WVPASS(resp.check_nonce(req)); WvX509 signing_cert = resp.get_signing_cert(); WVPASS(signing_cert.isok()); WVPASSEQ(signing_cert.get_subject(), ocspcert.get_subject()); WVPASS(resp.signedbycert(ocspcert)); WVFAIL(resp.signedbycert(cert)); } ::unlink(reqfname); ::unlink(respfname); ::unlink(indexfname); ::unlink(cafname); ::unlink(cakeyfname); ::unlink(ocspfname); ::unlink(ocspkeyfname); return resp.get_status(cert, cacert); } WVTEST_MAIN("encoding request") { WvRSAKey rsakey(DEFAULT_KEYLEN); WvString certreq = WvX509Mgr::certreq("cn=test.signed.com,dc=signed,dc=com", rsakey); WvX509Mgr cacert("CN=test.foo.com,DC=foo,DC=com", DEFAULT_KEYLEN, true); // cacert.set_ext_key_usage("OCSP Signing"); // cacert.signcert(cacert); // resign self WvX509Mgr cert; // only need wvx509mgr to test bogus signer problem WvString certpem = cacert.signreq(certreq); cert.decode(WvX509Mgr::CertPEM, certpem); cert.set_rsa(&rsakey); // this test breaks after 2020. oh well. static const char *EXPDATE = "202010194703Z"; //dec 10, 2049 static const char *REVDATE = "071211195254Z"; //dec 11 2007 { WvSystem caller("openssl", "version"); if (caller.go()) { WVFAIL("Failed to run openssl utility, is it installed and in your PATH?"); return; } } // unknown, because the cert's serial not in CRL list WVPASSEQ(test_ocsp_req(cert, cacert, cacert, ""), WvOCSPResp::Unknown); // revoked WVPASSEQ(test_ocsp_req(cert, cacert, cacert, WvString("R\t%s\t%s\t%s\tunknown\t%s\n", EXPDATE, REVDATE, cert.get_serial(true), cert.get_subject())), WvOCSPResp::Revoked); // good WVPASSEQ(test_ocsp_req(cert, cacert, cacert, WvString("V\t%s\t%s\t%s\tunknown\t%s\n", EXPDATE, REVDATE, cert.get_serial(true), cert.get_subject())), WvOCSPResp::Good); }