# class OpenSSL::Timestamp::Response

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`.

### Constants

GRANTED

  Indicates a successful response. Equal to `0`.

GRANTED_WITH_MODS

  Indicates a successful response that probably contains modifications from the initial request. Equal to `1`.

REJECTION

  Indicates a failure. No timestamp token was created. Equal to `2`.

REVOCATION_NOTIFICATION

  Indicates a failure. No timestamp token was created. A certificate has been revoked. Equal to `5`.

REVOCATION_WARNING

  Indicates a failure. No timestamp token was created. Revocation of a certificate is imminent. Equal to `4`.

WAITING

  Indicates a failure. No timestamp token was created. Equal to `3`.

### Public Class Methods

OpenSSL::Timestamp::Response.new(file) → response
OpenSSL::Timestamp::Response.new(string) → response
Source

    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;
    }

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.

### Public Instance Methods

failure_info → nil or symbol
Source

    static VALUE
    ossl_ts_resp_get_failure_info(VALUE self)
    {
        TS_RESP *resp;
        TS_STATUS_INFO *si;

        /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this
         * const. */
        #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
        const ASN1_BIT_STRING *fi;
        #else
        ASN1_BIT_STRING *fi;
        #endif

        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.");
    }

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 the `Request` is 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 - `Timestamp` creation failed due to an internal error that occurred on the timestamp server

status → BN (never nil)
Source

    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);
    }

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`.

status_text → Array of strings or nil
Source

    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;
    }

In cases of failure this field may contain an array of strings further describing the origin of the failure.

to_der → string
Source

    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);
    }

Returns the `Response` in DER-encoded form.

to_text ()
Source

    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 or OpenSSL::PKCS7
Source

    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);
    }

If a timestamp token is present, this returns it in the form of a `OpenSSL::PKCS7`.

token_info → nil or OpenSSL::Timestamp::TokenInfo
Source

    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;
    }

Get the response’s token info if present.

tsa_certificate → OpenSSL::X509::Certificate or nil
Source

    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);
    }

If the `Request` specified to request the TSA certificate (Request#cert_requested = true), then this field contains the certificate of the timestamp authority.

verify(Request, root_store) → Response
verify(Request, root_store, [intermediate_cert]) → Response
Source

    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);
        }

        TS_VERIFY_CTX_set_certs(ctx, x509inter);
        TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
        TS_VERIFY_CTX_set_store(ctx, x509st);

        ok = TS_RESP_verify_response(ctx, resp);
        /*
         * TS_VERIFY_CTX_set_store() call above does not increment the reference
         * counter, so it must be unset before TS_VERIFY_CTX_free() is called.
         */
        TS_VERIFY_CTX_set_store(ctx, NULL);
        TS_VERIFY_CTX_free(ctx);

        if (!ok)
            ossl_raise(eTimestampError, "TS_RESP_verify_response");

        return self;
    }

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

- `TimestampError` if 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.