<commit_before>/*
 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "crypto/x509.h"

ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
        ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
        ASN1_EMBED(X509_CINF, serialNumber, ASN1_INTEGER),
        ASN1_EMBED(X509_CINF, signature, X509_ALGOR),
        ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
        ASN1_EMBED(X509_CINF, validity, X509_VAL),
        ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
        ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
        ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
        ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
        ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)

IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
/* X509 top level structure needs a bit of customisation */

extern void ossl_policy_cache_free(X509_POLICY_CACHE *cache);

static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                   void *exarg)
{
    X509 *ret = (X509 *)*pval;

    switch (operation) {

    case ASN1_OP_D2I_PRE:
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
        X509_CERT_AUX_free(ret->aux);
        ASN1_OCTET_STRING_free(ret->skid);
        AUTHORITY_KEYID_free(ret->akid);
        CRL_DIST_POINTS_free(ret->crldp);
        ossl_policy_cache_free(ret->policy_cache);
        GENERAL_NAMES_free(ret->altname);
        NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
        sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
        ASIdentifiers_free(ret->rfc3779_asid);
#endif
        ASN1_OCTET_STRING_free(ret->distinguishing_id);

        /* fall thru */

    case ASN1_OP_NEW_POST:
        ret->ex_cached = 0;
        ret->ex_kusage = 0;
        ret->ex_xkusage = 0;
        ret->ex_nscert = 0;
        ret->ex_flags = 0;
        ret->ex_pathlen = -1;
        ret->ex_pcpathlen = -1;
        ret->skid = NULL;
        ret->akid = NULL;
        ret->policy_cache = NULL;
        ret->altname = NULL;
        ret->nc = NULL;
#ifndef OPENSSL_NO_RFC3779
        ret->rfc3779_addr = NULL;
        ret->rfc3779_asid = NULL;
#endif
        ret->distinguishing_id = NULL;
        ret->aux = NULL;
        ret->crldp = NULL;
        if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data))
            return 0;
        break;

    case ASN1_OP_FREE_POST:
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
        X509_CERT_AUX_free(ret->aux);
        ASN1_OCTET_STRING_free(ret->skid);
        AUTHORITY_KEYID_free(ret->akid);
        CRL_DIST_POINTS_free(ret->crldp);
        ossl_policy_cache_free(ret->policy_cache);
        GENERAL_NAMES_free(ret->altname);
        NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
        sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
        ASIdentifiers_free(ret->rfc3779_asid);
#endif
        ASN1_OCTET_STRING_free(ret->distinguishing_id);
        OPENSSL_free(ret->propq);
        break;

    case ASN1_OP_DUP_POST:
        {
            X509 *old = exarg;

            if (!ossl_x509_set0_libctx(ret, old->libctx, old->propq))
                return 0;
        }
        break;
    default:
        break;
    }

    return 1;
}

ASN1_SEQUENCE_ref(X509, x509_cb) = {
        ASN1_EMBED(X509, cert_info, X509_CINF),
        ASN1_EMBED(X509, sig_alg, X509_ALGOR),
        ASN1_EMBED(X509, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509, X509)

IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(X509, X509, X509)
IMPLEMENT_ASN1_DUP_FUNCTION(X509)

X509 *d2i_X509(X509 **a, const unsigned char **in, long len)
{
    X509 *cert = NULL;
    int free_on_error = a != NULL && *a == NULL;

    cert = (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (X509_it()));
    /* Only cache the extensions if the cert object was passed in */
    if (cert != NULL && a != NULL) { /* then cert == *a */
        if (!ossl_x509v3_cache_extensions(cert)) {
            if (free_on_error)
                X509_free(cert);
            cert = NULL;
        }
    }
    return cert;
}
int i2d_X509(const X509 *a, unsigned char **out)
{
    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (X509_it()));
}

/*
 * This should only be used if the X509 object was embedded inside another
 * asn1 object and it needs a libctx to operate.
 * Use X509_new_ex() instead if possible.
 */
int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq)
{
    if (x != NULL) {
        x->libctx = libctx;
        OPENSSL_free(x->propq);
        x->propq = NULL;
        if (propq != NULL) {
            x->propq = OPENSSL_strdup(propq);
            if (x->propq == NULL)
                return 0;
        }
    }<commit_msg>x509: fix a dangling pointer<commit_after>/*
 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "crypto/x509.h"

ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
        ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
        ASN1_EMBED(X509_CINF, serialNumber, ASN1_INTEGER),
        ASN1_EMBED(X509_CINF, signature, X509_ALGOR),
        ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
        ASN1_EMBED(X509_CINF, validity, X509_VAL),
        ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
        ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
        ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
        ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
        ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)

IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
/* X509 top level structure needs a bit of customisation */

extern void ossl_policy_cache_free(X509_POLICY_CACHE *cache);

static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                   void *exarg)
{
    X509 *ret = (X509 *)*pval;

    switch (operation) {

    case ASN1_OP_D2I_PRE:
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
        X509_CERT_AUX_free(ret->aux);
        ASN1_OCTET_STRING_free(ret->skid);
        AUTHORITY_KEYID_free(ret->akid);
        CRL_DIST_POINTS_free(ret->crldp);
        ossl_policy_cache_free(ret->policy_cache);
        GENERAL_NAMES_free(ret->altname);
        NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
        sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
        ASIdentifiers_free(ret->rfc3779_asid);
#endif
        ASN1_OCTET_STRING_free(ret->distinguishing_id);

        /* fall thru */

    case ASN1_OP_NEW_POST:
        ret->ex_cached = 0;
        ret->ex_kusage = 0;
        ret->ex_xkusage = 0;
        ret->ex_nscert = 0;
        ret->ex_flags = 0;
        ret->ex_pathlen = -1;
        ret->ex_pcpathlen = -1;
        ret->skid = NULL;
        ret->akid = NULL;
        ret->policy_cache = NULL;
        ret->altname = NULL;
        ret->nc = NULL;
#ifndef OPENSSL_NO_RFC3779
        ret->rfc3779_addr = NULL;
        ret->rfc3779_asid = NULL;
#endif
        ret->distinguishing_id = NULL;
        ret->aux = NULL;
        ret->crldp = NULL;
        if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data))
            return 0;
        break;

    case ASN1_OP_FREE_POST:
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
        X509_CERT_AUX_free(ret->aux);
        ASN1_OCTET_STRING_free(ret->skid);
        AUTHORITY_KEYID_free(ret->akid);
        CRL_DIST_POINTS_free(ret->crldp);
        ossl_policy_cache_free(ret->policy_cache);
        GENERAL_NAMES_free(ret->altname);
        NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
        sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
        ASIdentifiers_free(ret->rfc3779_asid);
#endif
        ASN1_OCTET_STRING_free(ret->distinguishing_id);
        OPENSSL_free(ret->propq);
        break;

    case ASN1_OP_DUP_POST:
        {
            X509 *old = exarg;

            if (!ossl_x509_set0_libctx(ret, old->libctx, old->propq))
                return 0;
        }
        break;
    default:
        break;
    }

    return 1;
}

ASN1_SEQUENCE_ref(X509, x509_cb) = {
        ASN1_EMBED(X509, cert_info, X509_CINF),
        ASN1_EMBED(X509, sig_alg, X509_ALGOR),
        ASN1_EMBED(X509, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509, X509)

IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(X509, X509, X509)
IMPLEMENT_ASN1_DUP_FUNCTION(X509)

X509 *d2i_X509(X509 **a, const unsigned char **in, long len)
{
    X509 *cert = NULL;
    int free_on_error = a != NULL && *a == NULL;

    cert = (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (X509_it()));
    /* Only cache the extensions if the cert object was passed in */
    if (cert != NULL && a != NULL) { /* then cert == *a */
        if (!ossl_x509v3_cache_extensions(cert)) {
            if (free_on_error) {
                *a = NULL;
                X509_free(cert);
            }
            cert = NULL;
        }
    }
    return cert;
}
int i2d_X509(const X509 *a, unsigned char **out)
{
    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (X509_it()));
}

/*
 * This should only be used if the X509 object was embedded inside another
 * asn1 object and it needs a libctx to operate.
 * Use X509_new_ex() instead if possible.
 */
int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq)
{
    if (x != NULL) {
        x->libctx = libctx;
        OPENSSL_free(x->propq);
        x->propq = NULL;
        if (propq != NULL) {
            x->propq = OPENSSL_strdup(propq);
            if (x->propq == NULL)
                return 0;
        }
    }
{'fraction_non_alphanumeric': 0.11215131830340085, 'fraction_numerical': 0.05779518532670997, 'mean_word_length': 2.846069066862601, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 109, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3352298', 'n_tokens_mistral': 4491, 'n_tokens_neox': 4031, 'n_words': 746}