(root)/
Python-3.12.0/
Modules/
_ssl/
cert.c
       1  #include "Python.h"
       2  #include "../_ssl.h"
       3  
       4  #include "openssl/err.h"
       5  #include "openssl/bio.h"
       6  #include "openssl/pem.h"
       7  #include "openssl/x509.h"
       8  
       9  /*[clinic input]
      10  module _ssl
      11  class _ssl.Certificate "PySSLCertificate *" "PySSLCertificate_Type"
      12  [clinic start generated code]*/
      13  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=780fc647948cfffc]*/
      14  
      15  #include "clinic/cert.c.h"
      16  
      17  static PyObject *
      18  newCertificate(PyTypeObject *type, X509 *cert, int upref)
      19  {
      20      PySSLCertificate *self;
      21  
      22      assert(type != NULL && type->tp_alloc != NULL);
      23      assert(cert != NULL);
      24  
      25      self = (PySSLCertificate *) type->tp_alloc(type, 0);
      26      if (self == NULL) {
      27          return NULL;
      28      }
      29      if (upref == 1) {
      30          X509_up_ref(cert);
      31      }
      32      self->cert = cert;
      33      self->hash = -1;
      34  
      35      return (PyObject *) self;
      36  }
      37  
      38  static PyObject *
      39  _PySSL_CertificateFromX509(_sslmodulestate *state, X509 *cert, int upref)
      40  {
      41      return newCertificate(state->PySSLCertificate_Type, cert, upref);
      42  }
      43  
      44  static PyObject*
      45  _PySSL_CertificateFromX509Stack(_sslmodulestate *state, STACK_OF(X509) *stack, int upref)
      46  {
      47      int len, i;
      48      PyObject *result = NULL;
      49  
      50      len = sk_X509_num(stack);
      51      result = PyList_New(len);
      52      if (result == NULL) {
      53          return NULL;
      54      }
      55      for (i = 0; i < len; i++) {
      56          X509 *cert = sk_X509_value(stack, i);
      57          PyObject *ocert = _PySSL_CertificateFromX509(state, cert, upref);
      58          if (ocert == NULL) {
      59              Py_DECREF(result);
      60              return NULL;
      61          }
      62          PyList_SetItem(result, i, ocert);
      63      }
      64      return result;
      65  }
      66  
      67  /*[clinic input]
      68  _ssl.Certificate.public_bytes
      69      format: int(c_default="PY_SSL_ENCODING_PEM") = Encoding.PEM
      70  
      71  [clinic start generated code]*/
      72  
      73  static PyObject *
      74  _ssl_Certificate_public_bytes_impl(PySSLCertificate *self, int format)
      75  /*[clinic end generated code: output=c01ddbb697429e12 input=4d38c45e874b0e64]*/
      76  {
      77      BIO *bio;
      78      int retcode;
      79      PyObject *result;
      80      _sslmodulestate *state = get_state_cert(self);
      81  
      82      bio = BIO_new(BIO_s_mem());
      83      if (bio == NULL) {
      84          PyErr_SetString(state->PySSLErrorObject,
      85                          "failed to allocate BIO");
      86          return NULL;
      87      }
      88      switch(format) {
      89      case PY_SSL_ENCODING_PEM:
      90          retcode = PEM_write_bio_X509(bio, self->cert);
      91          break;
      92      case PY_SSL_ENCODING_PEM_AUX:
      93          retcode = PEM_write_bio_X509_AUX(bio, self->cert);
      94          break;
      95      case PY_SSL_ENCODING_DER:
      96          retcode = i2d_X509_bio(bio, self->cert);
      97          break;
      98      default:
      99          PyErr_SetString(PyExc_ValueError, "Unsupported format");
     100          BIO_free(bio);
     101          return NULL;
     102      }
     103      if (retcode != 1) {
     104          BIO_free(bio);
     105          _setSSLError(state, NULL, 0, __FILE__, __LINE__);
     106          return NULL;
     107      }
     108      if (format == PY_SSL_ENCODING_DER) {
     109          result = _PySSL_BytesFromBIO(state, bio);
     110      } else {
     111          result = _PySSL_UnicodeFromBIO(state, bio, "error");
     112      }
     113      BIO_free(bio);
     114      return result;
     115  }
     116  
     117  
     118  /*[clinic input]
     119  _ssl.Certificate.get_info
     120  
     121  [clinic start generated code]*/
     122  
     123  static PyObject *
     124  _ssl_Certificate_get_info_impl(PySSLCertificate *self)
     125  /*[clinic end generated code: output=0f0deaac54f4408b input=ba2c1694b39d0778]*/
     126  {
     127      return _decode_certificate(get_state_cert(self), self->cert);
     128  }
     129  
     130  static PyObject*
     131  _x509name_print(_sslmodulestate *state, X509_NAME *name, int indent, unsigned long flags)
     132  {
     133      PyObject *res;
     134      BIO *biobuf;
     135  
     136      biobuf = BIO_new(BIO_s_mem());
     137      if (biobuf == NULL) {
     138          PyErr_SetString(PyExc_MemoryError, "failed to allocate BIO");
     139          return NULL;
     140      }
     141  
     142      if (X509_NAME_print_ex(biobuf, name, indent, flags) <= 0) {
     143          _setSSLError(state, NULL, 0, __FILE__, __LINE__);
     144          BIO_free(biobuf);
     145          return NULL;
     146      }
     147      res = _PySSL_UnicodeFromBIO(state, biobuf, "strict");
     148      BIO_free(biobuf);
     149      return res;
     150  }
     151  
     152  /* ************************************************************************
     153   * PySSLCertificate_Type
     154   */
     155  
     156  static PyObject *
     157  certificate_repr(PySSLCertificate *self)
     158  {
     159      PyObject *osubject, *result;
     160  
     161      /* subject string is ASCII encoded, UTF-8 chars are quoted */
     162      osubject = _x509name_print(
     163          get_state_cert(self),
     164          X509_get_subject_name(self->cert),
     165          0,
     166          XN_FLAG_RFC2253
     167      );
     168      if (osubject == NULL)
     169          return NULL;
     170      result = PyUnicode_FromFormat(
     171          "<%s '%U'>",
     172          Py_TYPE(self)->tp_name, osubject
     173      );
     174      Py_DECREF(osubject);
     175      return result;
     176  }
     177  
     178  static Py_hash_t
     179  certificate_hash(PySSLCertificate *self)
     180  {
     181      if (self->hash == (Py_hash_t)-1) {
     182          unsigned long hash;
     183          hash = X509_subject_name_hash(self->cert);
     184          if ((Py_hash_t)hash == (Py_hash_t)-1) {
     185              self->hash = -2;
     186          } else {
     187              self->hash = (Py_hash_t)hash;
     188          }
     189      }
     190      return self->hash;
     191  }
     192  
     193  static PyObject *
     194  certificate_richcompare(PySSLCertificate *self, PyObject *other, int op)
     195  {
     196      int cmp;
     197      _sslmodulestate *state = get_state_cert(self);
     198  
     199      if (Py_TYPE(other) != state->PySSLCertificate_Type) {
     200          Py_RETURN_NOTIMPLEMENTED;
     201      }
     202      /* only support == and != */
     203      if ((op != Py_EQ) && (op != Py_NE)) {
     204          Py_RETURN_NOTIMPLEMENTED;
     205      }
     206      cmp = X509_cmp(self->cert, ((PySSLCertificate*)other)->cert);
     207      if (((op == Py_EQ) && (cmp == 0)) || ((op == Py_NE) && (cmp != 0))) {
     208          Py_RETURN_TRUE;
     209      } else {
     210          Py_RETURN_FALSE;
     211      }
     212  }
     213  
     214  static void
     215  certificate_dealloc(PySSLCertificate *self)
     216  {
     217      PyTypeObject *tp = Py_TYPE(self);
     218      X509_free(self->cert);
     219      Py_TYPE(self)->tp_free(self);
     220      Py_DECREF(tp);
     221  }
     222  
     223  static PyMethodDef certificate_methods[] = {
     224      /* methods */
     225      _SSL_CERTIFICATE_PUBLIC_BYTES_METHODDEF
     226      _SSL_CERTIFICATE_GET_INFO_METHODDEF
     227      {NULL, NULL}
     228  };
     229  
     230  static PyType_Slot PySSLCertificate_slots[] = {
     231      {Py_tp_dealloc, certificate_dealloc},
     232      {Py_tp_repr, certificate_repr},
     233      {Py_tp_hash, certificate_hash},
     234      {Py_tp_richcompare, certificate_richcompare},
     235      {Py_tp_methods, certificate_methods},
     236      {0, 0},
     237  };
     238  
     239  static PyType_Spec PySSLCertificate_spec = {
     240      "_ssl.Certificate",
     241      sizeof(PySSLCertificate),
     242      0,
     243      Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
     244      PySSLCertificate_slots,
     245  };