#include "Python.h"
#include "../_ssl.h"

#include "openssl/err.h"
#include "openssl/bio.h"
#include "openssl/pem.h"
#include "openssl/x509.h"

/*[clinic input]
module _ssl
class _ssl.Certificate "PySSLCertificate *" "PySSLCertificate_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=780fc647948cfffc]*/

#include "clinic/cert.c.h"

static PyObject *
newCertificate(PyTypeObject *type, X509 *cert, int upref)
{
    PySSLCertificate *self;

    assert(type != NULL && type->tp_alloc != NULL);
    assert(cert != NULL);

    self = (PySSLCertificate *) type->tp_alloc(type, 0);
    if (self == NULL) {
        return NULL;
    }
    if (upref == 1) {
        X509_up_ref(cert);
    }
    self->cert = cert;
    self->hash = -1;

    return (PyObject *) self;
}

static PyObject *
_PySSL_CertificateFromX509(_sslmodulestate *state, X509 *cert, int upref)
{
    return newCertificate(state->PySSLCertificate_Type, cert, upref);
}

static PyObject*
_PySSL_CertificateFromX509Stack(_sslmodulestate *state, STACK_OF(X509) *stack, int upref)
{
    int len, i;
    PyObject *result = NULL;

    len = sk_X509_num(stack);
    result = PyList_New(len);
    if (result == NULL) {
        return NULL;
    }
    for (i = 0; i < len; i++) {
        X509 *cert = sk_X509_value(stack, i);
        PyObject *ocert = _PySSL_CertificateFromX509(state, cert, upref);
        if (ocert == NULL) {
            Py_DECREF(result);
            return NULL;
        }
        PyList_SetItem(result, i, ocert);
    }
    return result;
}

/*[clinic input]
_ssl.Certificate.public_bytes
    format: int(c_default="PY_SSL_ENCODING_PEM") = Encoding.PEM

[clinic start generated code]*/

static PyObject *
_ssl_Certificate_public_bytes_impl(PySSLCertificate *self, int format)
/*[clinic end generated code: output=c01ddbb697429e12 input=4d38c45e874b0e64]*/
{
    BIO *bio;
    int retcode;
    PyObject *result;
    _sslmodulestate *state = get_state_cert(self);

    bio = BIO_new(BIO_s_mem());
    if (bio == NULL) {
        PyErr_SetString(state->PySSLErrorObject,
                        "failed to allocate BIO");
        return NULL;
    }
    switch(format) {
    case PY_SSL_ENCODING_PEM:
        retcode = PEM_write_bio_X509(bio, self->cert);
        break;
    case PY_SSL_ENCODING_PEM_AUX:
        retcode = PEM_write_bio_X509_AUX(bio, self->cert);
        break;
    case PY_SSL_ENCODING_DER:
        retcode = i2d_X509_bio(bio, self->cert);
        break;
    default:
        PyErr_SetString(PyExc_ValueError, "Unsupported format");
        BIO_free(bio);
        return NULL;
    }
    if (retcode != 1) {
        BIO_free(bio);
        _setSSLError(state, NULL, 0, __FILE__, __LINE__);
        return NULL;
    }
    if (format == PY_SSL_ENCODING_DER) {
        result = _PySSL_BytesFromBIO(state, bio);
    } else {
        result = _PySSL_UnicodeFromBIO(state, bio, "error");
    }
    BIO_free(bio);
    return result;
}


/*[clinic input]
_ssl.Certificate.get_info

[clinic start generated code]*/

static PyObject *
_ssl_Certificate_get_info_impl(PySSLCertificate *self)
/*[clinic end generated code: output=0f0deaac54f4408b input=ba2c1694b39d0778]*/
{
    return _decode_certificate(get_state_cert(self), self->cert);
}

static PyObject*
_x509name_print(_sslmodulestate *state, X509_NAME *name, int indent, unsigned long flags)
{
    PyObject *res;
    BIO *biobuf;

    biobuf = BIO_new(BIO_s_mem());
    if (biobuf == NULL) {
        PyErr_SetString(PyExc_MemoryError, "failed to allocate BIO");
        return NULL;
    }

    if (X509_NAME_print_ex(biobuf, name, indent, flags) <= 0) {
        _setSSLError(state, NULL, 0, __FILE__, __LINE__);
        BIO_free(biobuf);
        return NULL;
    }
    res = _PySSL_UnicodeFromBIO(state, biobuf, "strict");
    BIO_free(biobuf);
    return res;
}

/* ************************************************************************
 * PySSLCertificate_Type
 */

static PyObject *
certificate_repr(PySSLCertificate *self)
{
    PyObject *osubject, *result;

    /* subject string is ASCII encoded, UTF-8 chars are quoted */
    osubject = _x509name_print(
        get_state_cert(self),
        X509_get_subject_name(self->cert),
        0,
        XN_FLAG_RFC2253
    );
    if (osubject == NULL)
        return NULL;
    result = PyUnicode_FromFormat(
        "<%s '%U'>",
        Py_TYPE(self)->tp_name, osubject
    );
    Py_DECREF(osubject);
    return result;
}

static Py_hash_t
certificate_hash(PySSLCertificate *self)
{
    if (self->hash == (Py_hash_t)-1) {
        unsigned long hash;
        hash = X509_subject_name_hash(self->cert);
        if ((Py_hash_t)hash == (Py_hash_t)-1) {
            self->hash = -2;
        } else {
            self->hash = (Py_hash_t)hash;
        }
    }
    return self->hash;
}

static PyObject *
certificate_richcompare(PySSLCertificate *self, PyObject *other, int op)
{
    int cmp;
    _sslmodulestate *state = get_state_cert(self);

    if (Py_TYPE(other) != state->PySSLCertificate_Type) {
        Py_RETURN_NOTIMPLEMENTED;
    }
    /* only support == and != */
    if ((op != Py_EQ) && (op != Py_NE)) {
        Py_RETURN_NOTIMPLEMENTED;
    }
    cmp = X509_cmp(self->cert, ((PySSLCertificate*)other)->cert);
    if (((op == Py_EQ) && (cmp == 0)) || ((op == Py_NE) && (cmp != 0))) {
        Py_RETURN_TRUE;
    } else {
        Py_RETURN_FALSE;
    }
}

static void
certificate_dealloc(PySSLCertificate *self)
{
    PyTypeObject *tp = Py_TYPE(self);
    X509_free(self->cert);
    Py_TYPE(self)->tp_free(self);
    Py_DECREF(tp);
}

static PyMethodDef certificate_methods[] = {
    /* methods */
    _SSL_CERTIFICATE_PUBLIC_BYTES_METHODDEF
    _SSL_CERTIFICATE_GET_INFO_METHODDEF
    {NULL, NULL}
};

static PyType_Slot PySSLCertificate_slots[] = {
    {Py_tp_dealloc, certificate_dealloc},
    {Py_tp_repr, certificate_repr},
    {Py_tp_hash, certificate_hash},
    {Py_tp_richcompare, certificate_richcompare},
    {Py_tp_methods, certificate_methods},
    {0, 0},
};

static PyType_Spec PySSLCertificate_spec = {
    "_ssl.Certificate",
    sizeof(PySSLCertificate),
    0,
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
    PySSLCertificate_slots,
};
