Class: OpenSSL::Timestamp::Response
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | ext/openssl/ossl_ts.c |
Overview
Immutable and read-only representation of a timestamp response returned from a timestamp server after receiving an associated Request. Allows access to specific information about the response but also allows to verify the Response.
Constant Summary
-
GRANTED =
# File 'ext/openssl/ossl_ts.c', line 1469
Indicates a successful response. Equal to
0.INT2NUM(TS_STATUS_GRANTED)
-
GRANTED_WITH_MODS =
# File 'ext/openssl/ossl_ts.c', line 1474
Indicates a successful response that probably contains modifications from the initial request. Equal to
1.INT2NUM(TS_STATUS_GRANTED_WITH_MODS)
-
REJECTION =
# File 'ext/openssl/ossl_ts.c', line 1478
Indicates a failure. No timestamp token was created. Equal to
2.INT2NUM(TS_STATUS_REJECTION)
-
REVOCATION_NOTIFICATION =
# File 'ext/openssl/ossl_ts.c', line 1492
Indicates a failure. No timestamp token was created. A certificate has been revoked. Equal to
5.INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION)
-
REVOCATION_WARNING =
# File 'ext/openssl/ossl_ts.c', line 1487
Indicates a failure. No timestamp token was created. Revocation of a certificate is imminent. Equal to
4.INT2NUM(TS_STATUS_REVOCATION_WARNING)
-
WAITING =
# File 'ext/openssl/ossl_ts.c', line 1482
Indicates a failure. No timestamp token was created. Equal to
3.INT2NUM(TS_STATUS_WAITING)
Class Method Summary
-
.new(file) ⇒ Response
constructor
Creates a
Responsefrom aFileorstringparameter, the correspondingFileorstringmust be DER-encoded.
Instance Method Summary
-
#failure_info ⇒ nil, Symbol
In cases no timestamp token has been created, this field contains further info about the reason why response creation failed.
-
#status ⇒ BN (never nil)
Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING, REVOCATION_WARNING or REVOCATION_NOTIFICATION.
-
#status_text ⇒ Array of strings?
In cases of failure this field may contain an array of strings further describing the origin of the failure.
-
#to_der ⇒ String
Returns the
Responsein DER-encoded form. - #to_text
-
#token ⇒ nil, OpenSSL::PKCS7
If a timestamp token is present, this returns it in the form of a
::OpenSSL::PKCS7. -
#token_info ⇒ nil, OpenSSL::Timestamp::TokenInfo
Get the response’s token info if present.
-
#tsa_certificate ⇒ OpenSSL::X509::Certificate?
If the
Requestspecified to request the TSA certificate (Request#cert_requested = true), then this field contains the certificate of the timestamp authority. -
#verify(Request, root_store) ⇒ Response
Verifies a timestamp token by checking the signature, validating the certificate chain implied by tsa_certificate and by checking conformance to a given
Request.
Constructor Details
.new(file) ⇒ Response
.new(string) ⇒ Response
Response
.new(string) ⇒ Response
Creates a Response from a File or string parameter, the corresponding File or string must be DER-encoded. Please note that Response is an immutable read-only class. If you’d like to create timestamps please refer to Factory instead.
# File 'ext/openssl/ossl_ts.c', line 556
static VALUE
ossl_ts_resp_initialize(VALUE self, VALUE der)
{
TS_RESP *ts_resp = DATA_PTR(self);
BIO *in;
der = ossl_to_der_if_possible(der);
in = ossl_obj2bio(&der);
ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
BIO_free(in);
if (!ts_resp) {
DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp response");
}
DATA_PTR(self) = ts_resp;
return self;
}
Instance Method Details
#failure_info ⇒ nil, Symbol
In cases no timestamp token has been created, this field contains further info about the reason why response creation failed. The method returns either nil (the request was successful and a timestamp token was created) or one of the following:
-
:BAD_ALG- Indicates that the timestamp server rejects the message imprint algorithm used in the Request -
:BAD_REQUEST- Indicates that the timestamp server was not able to process the Request properly -
:BAD_DATA_FORMAT- Indicates that the timestamp server was not able to parse certain data in the Request -
:TIME_NOT_AVAILABLE- Indicates that the server could not access its time source -
:UNACCEPTED_POLICY- Indicates that the requested policy identifier is not recognized or supported by the timestamp server -
:UNACCEPTED_EXTENSIION- Indicates that an extension in theRequestis not supported by the timestamp server -
:ADD_INFO_NOT_AVAILABLE-Indicates that additional information requested is either not understood or currently not available -
:SYSTEM_FAILURE-::OpenSSL::Timestampcreation failed due to an internal error that occurred on the timestamp server
# File 'ext/openssl/ossl_ts.c', line 622
static VALUE
ossl_ts_resp_get_failure_info(VALUE self)
{
TS_RESP *resp;
TS_STATUS_INFO *si;
const ASN1_BIT_STRING *fi;
GetTSResponse(self, resp);
si = TS_RESP_get_status_info(resp);
fi = TS_STATUS_INFO_get0_failure_info(si);
if (!fi)
return Qnil;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG))
return sBAD_ALG;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST))
return sBAD_REQUEST;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT))
return sBAD_DATA_FORMAT;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE))
return sTIME_NOT_AVAILABLE;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY))
return sUNACCEPTED_POLICY;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION))
return sUNACCEPTED_EXTENSION;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE))
return sADD_INFO_NOT_AVAILABLE;
if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE))
return sSYSTEM_FAILURE;
ossl_raise(eTimestampError, "Unrecognized failure info.");
}
#status ⇒ BN (never nil)
Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING, REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has been created only in case status is equal to GRANTED or GRANTED_WITH_MODS.
# File 'ext/openssl/ossl_ts.c', line 583
static VALUE
ossl_ts_resp_get_status(VALUE self)
{
TS_RESP *resp;
TS_STATUS_INFO *si;
const ASN1_INTEGER *st;
GetTSResponse(self, resp);
si = TS_RESP_get_status_info(resp);
st = TS_STATUS_INFO_get0_status(si);
return asn1integer_to_num(st);
}
#status_text ⇒ Array of strings?
In cases of failure this field may contain an array of strings further describing the origin of the failure.
# File 'ext/openssl/ossl_ts.c', line 661
static VALUE
ossl_ts_resp_get_status_text(VALUE self)
{
TS_RESP *resp;
TS_STATUS_INFO *si;
const STACK_OF(ASN1_UTF8STRING) *text;
ASN1_UTF8STRING *current;
int i;
VALUE ret = rb_ary_new();
GetTSResponse(self, resp);
si = TS_RESP_get_status_info(resp);
if ((text = TS_STATUS_INFO_get0_text(si))) {
for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
current = sk_ASN1_UTF8STRING_value(text, i);
rb_ary_push(ret, asn1str_to_str(current));
}
}
return ret;
}
#to_der ⇒ String
Returns the Response in DER-encoded form.
# File 'ext/openssl/ossl_ts.c', line 761
static VALUE
ossl_ts_resp_to_der(VALUE self)
{
TS_RESP *resp;
GetTSResponse(self, resp);
return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP);
}
#to_text
[ GitHub ]# File 'ext/openssl/ossl_ts.c', line 770
static VALUE
ossl_ts_resp_to_text(VALUE self)
{
TS_RESP *resp;
BIO *out;
GetTSResponse(self, resp);
out = BIO_new(BIO_s_mem());
if (!out) ossl_raise(eTimestampError, NULL);
if (!TS_RESP_print_bio(out, resp)) {
BIO_free(out);
ossl_raise(eTimestampError, NULL);
}
return ossl_membio2str(out);
}
#token ⇒ nil, OpenSSL::PKCS7
If a timestamp token is present, this returns it in the form of a ::OpenSSL::PKCS7.
# File 'ext/openssl/ossl_ts.c', line 690
static VALUE
ossl_ts_resp_get_token(VALUE self)
{
TS_RESP *resp;
PKCS7 *p7;
GetTSResponse(self, resp);
if (!(p7 = TS_RESP_get_token(resp)))
return Qnil;
return ossl_pkcs7_new(p7);
}
#token_info ⇒ nil, OpenSSL::Timestamp::TokenInfo
Get the response’s token info if present.
# File 'ext/openssl/ossl_ts.c', line 708
static VALUE
ossl_ts_resp_get_token_info(VALUE self)
{
TS_RESP *resp;
TS_TST_INFO *info, *copy;
VALUE obj;
GetTSResponse(self, resp);
if (!(info = TS_RESP_get_tst_info(resp)))
return Qnil;
obj = NewTSTokenInfo(cTimestampTokenInfo);
if (!(copy = TS_TST_INFO_dup(info)))
ossl_raise(eTimestampError, NULL);
SetTSTokenInfo(obj, copy);
return obj;
}
#tsa_certificate ⇒ OpenSSL::X509::Certificate?
If the Request specified to request the TSA certificate (Request#cert_requested = true), then this field contains the certificate of the timestamp authority.
# File 'ext/openssl/ossl_ts.c', line 737
static VALUE
ossl_ts_resp_get_tsa_certificate(VALUE self)
{
TS_RESP *resp;
PKCS7 *p7;
PKCS7_SIGNER_INFO *ts_info;
X509 *cert;
GetTSResponse(self, resp);
if (!(p7 = TS_RESP_get_token(resp)))
return Qnil;
ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0);
cert = PKCS7_cert_from_signer_info(p7, ts_info);
if (!cert)
return Qnil;
return ossl_x509_new(cert);
}
#verify(Request, root_store) ⇒ Response
#verify(Request, root_store, [intermediate_cert]) ⇒ Response
Response
#verify(Request, root_store, [intermediate_cert]) ⇒ Response
Verifies a timestamp token by checking the signature, validating the certificate chain implied by tsa_certificate and by checking conformance to a given Request. Mandatory parameters are the Request associated to this Response, and an ::OpenSSL::X509::Store of trusted roots.
Intermediate certificates can optionally be supplied for creating the certificate chain. These intermediate certificates must all be instances of ::OpenSSL::X509::Certificate.
If validation fails, several kinds of exceptions can be raised:
-
TypeError if types don’t fit
-
TimestampErrorif something is wrong with the timestamp token itself, if it is not conformant to the Request, or if validation of the timestamp certificate chain fails.
# File 'ext/openssl/ossl_ts.c', line 809
static VALUE
ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
{
VALUE ts_req, store, intermediates;
TS_RESP *resp;
TS_REQ *req;
X509_STORE *x509st;
TS_VERIFY_CTX *ctx;
STACK_OF(X509) *x509inter = NULL;
PKCS7* p7;
X509 *cert;
int status, i, ok;
rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates);
GetTSResponse(self, resp);
GetTSRequest(ts_req, req);
x509st = GetX509StorePtr(store);
if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) {
ossl_raise(eTimestampError, "Error when creating the verification context.");
}
if (!NIL_P(intermediates)) {
x509inter = ossl_protect_x509_ary2sk(intermediates, &status);
if (status) {
TS_VERIFY_CTX_free(ctx);
rb_jump_tag(status);
}
} else if (!(x509inter = sk_X509_new_null())) {
TS_VERIFY_CTX_free(ctx);
ossl_raise(eTimestampError, "sk_X509_new_null");
}
if (!(p7 = TS_RESP_get_token(resp))) {
TS_VERIFY_CTX_free(ctx);
sk_X509_pop_free(x509inter, X509_free);
ossl_raise(eTimestampError, "TS_RESP_get_token");
}
for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) {
cert = sk_X509_value(p7->d.sign->cert, i);
if (!sk_X509_push(x509inter, cert)) {
sk_X509_pop_free(x509inter, X509_free);
TS_VERIFY_CTX_free(ctx);
ossl_raise(eTimestampError, "sk_X509_push");
}
X509_up_ref(cert);
}
if (!X509_STORE_up_ref(x509st)) {
sk_X509_pop_free(x509inter, X509_free);
TS_VERIFY_CTX_free(ctx);
ossl_raise(eTimestampError, "X509_STORE_up_ref");
}
#ifdef HAVE_TS_VERIFY_CTX_SET0_CERTS
TS_VERIFY_CTX_set0_certs(ctx, x509inter);
TS_VERIFY_CTX_set0_store(ctx, x509st);
#else
# if OSSL_OPENSSL_PREREQ(3, 0, 0) || OSSL_IS_LIBRESSL
TS_VERIFY_CTX_set_certs(ctx, x509inter);
# else
TS_VERIFY_CTS_set_certs(ctx, x509inter);
# endif
TS_VERIFY_CTX_set_store(ctx, x509st);
#endif
TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
ok = TS_RESP_verify_response(ctx, resp);
TS_VERIFY_CTX_free(ctx);
if (!ok)
ossl_raise(eTimestampError, "TS_RESP_verify_response");
return self;
}