123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- #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,
- };
|