/* * Given a X509_NAME object and a name identifier, set the corresponding * attribute to the given string. Used by the setattr function. * * Arguments: name - The X509_NAME object * nid - The name identifier * value - The string to set * Returns: 0 for success, -1 on failure */ static int set_name_by_nid(X509_NAME *name, int nid, char *utf8string) { X509_NAME_ENTRY *ne; int i, entry_count, temp_nid; /* If there's an old entry for this NID, remove it */ entry_count = X509_NAME_entry_count(name); for (i = 0; i < entry_count; i++) { ne = X509_NAME_get_entry(name, i); temp_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)); if (temp_nid == nid) { ne = X509_NAME_delete_entry(name, i); X509_NAME_ENTRY_free(ne); break; } } /* Add the new entry */ if (!X509_NAME_add_entry_by_NID(name, nid, MBSTRING_UTF8, (unsigned char *)utf8string, -1, -1, 0)) { exception_from_error_queue(crypto_Error); return -1; } return 0; }
@return: The public key\n\ "; static PyObject * crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args) { crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int); EVP_PKEY *pkey; crypto_PKeyObj *py_pkey; if (!PyArg_ParseTuple(args, ":get_pubkey")) return NULL; if ((pkey = X509_get_pubkey(self->x509)) == NULL) { exception_from_error_queue(crypto_Error); return NULL; } py_pkey = crypto_PKey_New(pkey, 1); if (py_pkey != NULL) { py_pkey->only_public = 1; } return (PyObject *)py_pkey; }
/* * String representation of an X509Name * * Arguments: self - The X509Name object * Returns: A string representation of the object */ static PyObject * crypto_X509Name_repr(crypto_X509NameObj *self) { char tmpbuf[512] = ""; char realbuf[512+64]; if (X509_NAME_oneline(self->x509_name, tmpbuf, 512) == NULL) { exception_from_error_queue(crypto_Error); return NULL; } else { /* This is safe because tmpbuf is max 512 characters */ sprintf(realbuf, "<X509Name object '%s'>", tmpbuf); return PyText_FromString(realbuf); } }
static PyObject * ssl_Connection_get_client_ca_list(ssl_ConnectionObj *self, PyObject *args) { STACK_OF(X509_NAME) *CANames; PyObject *CAList; int i, n; if (!PyArg_ParseTuple(args, ":get_client_ca_list")) { return NULL; } CANames = SSL_get_client_CA_list(self->ssl); if (CANames == NULL) { return PyList_New(0); } n = sk_X509_NAME_num(CANames); CAList = PyList_New(n); if (CAList == NULL) { return NULL; } for (i = 0; i < n; i++) { X509_NAME *CAName; PyObject *CA; CAName = X509_NAME_dup(sk_X509_NAME_value(CANames, i)); if (CAName == NULL) { Py_DECREF(CAList); exception_from_error_queue(ssl_Error); return NULL; } CA = (PyObject *)new_x509name(CAName, 1); if (CA == NULL) { X509_NAME_free(CAName); Py_DECREF(CAList); return NULL; } if (PyList_SetItem(CAList, i, CA)) { Py_DECREF(CA); Py_DECREF(CAList); return NULL; } } return CAList; }
/* * Print a nice text representation of the certificate request. */ static PyObject * crypto_X509Extension_str(crypto_X509ExtensionObj *self) { int str_len; char *tmp_str; PyObject *str; BIO *bio = BIO_new(BIO_s_mem()); if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0)) { BIO_free(bio); exception_from_error_queue(crypto_Error); return NULL; } str_len = BIO_get_mem_data(bio, &tmp_str); str = PyText_FromStringAndSize(tmp_str, str_len); BIO_free(bio); return str; }
/* * Return a name string given a X509_NAME object and a name identifier. Used * by the getattr function. * * Arguments: name - The X509_NAME object * nid - The name identifier * Returns: The name as a Python string object */ static int get_name_by_nid(X509_NAME *name, int nid, char **utf8string) { int entry_idx; X509_NAME_ENTRY *entry; ASN1_STRING *data; int len; if ((entry_idx = X509_NAME_get_index_by_NID(name, nid, -1)) == -1) { return 0; } entry = X509_NAME_get_entry(name, entry_idx); data = X509_NAME_ENTRY_get_data(entry); if ((len = ASN1_STRING_to_UTF8((unsigned char **)utf8string, data)) < 0) { exception_from_error_queue(crypto_Error); return -1; } return len; }
@return: modulus\n\ "; static PyObject * crypto_X509_modulus(crypto_X509Obj *self, PyObject *args) { EVP_PKEY *pkey; PyObject *str; char *tmp_str; int str_len; BIO *bio = BIO_new(BIO_s_mem()); if (!PyArg_ParseTuple(args, ":modulus")) { BIO_free(bio); return NULL; } if ((pkey = X509_get_pubkey(self->x509)) == NULL) { BIO_free(bio); exception_from_error_queue(crypto_Error); return NULL; } if (pkey->type == EVP_PKEY_RSA) BN_print(bio, pkey->pkey.rsa->n); else if (pkey->type == EVP_PKEY_DSA) BN_print(bio, pkey->pkey.dsa->pub_key); EVP_PKEY_free(pkey); str_len = BIO_get_mem_data(bio, &tmp_str); str = PyString_FromStringAndSize(tmp_str, str_len); BIO_free(bio); return str; }
:return: The digest of the object\n\ "; static PyObject * crypto_X509_digest(crypto_X509Obj *self, PyObject *args) { unsigned char fp[EVP_MAX_MD_SIZE]; char *tmp; char *digest_name; unsigned int len,i; PyObject *ret; const EVP_MD *digest; if (!PyArg_ParseTuple(args, "s:digest", &digest_name)) return NULL; if ((digest = EVP_get_digestbyname(digest_name)) == NULL) { PyErr_SetString(PyExc_ValueError, "No such digest method"); return NULL; } if (!X509_digest(self->x509,digest,fp,&len)) { exception_from_error_queue(crypto_Error); } tmp = malloc(3*len+1); memset(tmp, 0, 3*len+1); for (i = 0; i < len; i++) { sprintf(tmp+i*3,"%02X:",fp[i]); } tmp[3*len-1] = 0; ret = PyBytes_FromStringAndSize(tmp,3*len-1); free(tmp); return ret; }
wait for a ZeroReturnError on a recv() method call\n\ "; static PyObject * ssl_Connection_shutdown(ssl_ConnectionObj *self, PyObject *args) { int ret; if (!PyArg_ParseTuple(args, ":shutdown")) return NULL; MY_BEGIN_ALLOW_THREADS(self->tstate) ret = SSL_shutdown(self->ssl); MY_END_ALLOW_THREADS(self->tstate) if (PyErr_Occurred()) { flush_error_queue(); return NULL; } if (ret < 0) { exception_from_error_queue(ssl_Error); return NULL; } else if (ret > 0) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } }
/* * Handle errors raised by BIO functions. * * Arguments: bio - The BIO object * ret - The return value of the BIO_ function. * Returns: None, the calling function should return NULL; */ static void handle_bio_errors(BIO* bio, int ret) { if (BIO_should_retry(bio)) { if (BIO_should_read(bio)) { PyErr_SetNone(ssl_WantReadError); } else if (BIO_should_write(bio)) { PyErr_SetNone(ssl_WantWriteError); } else if (BIO_should_io_special(bio)) { /* * It's somewhat unclear what this means. From the OpenSSL source, * it seems like it should not be triggered by the memory BIO, so * for the time being, this case shouldn't come up. The SSL BIO * (which I think should be named the socket BIO) may trigger this * case if its socket is not yet connected or it is busy doing * something related to x509. */ PyErr_SetString(PyExc_ValueError, "BIO_should_io_special"); } else { /* * I hope this is dead code. The BIO documentation suggests that * one of the above three checks should always be true. */ PyErr_SetString(PyExc_ValueError, "unknown bio failure"); } } else { /* * If we aren't to retry, it's really an error, so fall back to the * normal error reporting code. However, the BIO interface does not * specify a uniform error reporting mechanism. We can only hope that * the code which triggered the error also kindly pushed something onto * the error stack. */ exception_from_error_queue(ssl_Error); } }
/* * Constructor for X509Extension, never called by Python code directly * * Arguments: type_name - ??? * critical - ??? * value - ??? * subject - An x509v3 certificate which is the subject for this extension. * issuer - An x509v3 certificate which is the issuer for this extension. * Returns: The newly created X509Extension object */ crypto_X509ExtensionObj * crypto_X509Extension_New(char *type_name, int critical, char *value, crypto_X509Obj *subject, crypto_X509Obj *issuer) { X509V3_CTX ctx; crypto_X509ExtensionObj *self; char* value_with_critical = NULL; /* * A context is necessary for any extension which uses the r2i conversion * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx. * Start off by initializing most of the fields to NULL. */ X509V3_set_ctx(&ctx, NULL, NULL, NULL, NULL, 0); /* * We have no configuration database - but perhaps we should (some * extensions may require it). */ X509V3_set_ctx_nodb(&ctx); /* * Initialize the subject and issuer, if appropriate. ctx is a local, and * as far as I can tell none of the X509V3_* APIs invoked here steal any * references, so no need to incref subject or issuer. */ if (subject) { ctx.subject_cert = subject->x509; } if (issuer) { ctx.issuer_cert = issuer->x509; } self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type); if (self == NULL) { goto error; } self->dealloc = 0; /* There are other OpenSSL APIs which would let us pass in critical * separately, but they're harder to use, and since value is already a pile * of crappy junk smuggling a ton of utterly important structured data, * what's the point of trying to avoid nasty stuff with strings? (However, * X509V3_EXT_i2d in particular seems like it would be a better API to * invoke. I do not know where to get the ext_struc it desires for its * last parameter, though.) */ value_with_critical = malloc(strlen("critical,") + strlen(value) + 1); if (!value_with_critical) { goto critical_malloc_error; } if (critical) { strcpy(value_with_critical, "critical,"); strcpy(value_with_critical + strlen("critical,"), value); } else { strcpy(value_with_critical, value); } self->x509_extension = X509V3_EXT_nconf( NULL, &ctx, type_name, value_with_critical); free(value_with_critical); if (!self->x509_extension) { goto nconf_error; } self->dealloc = 1; return self; nconf_error: exception_from_error_queue(crypto_Error); critical_malloc_error: Py_XDECREF(self); error: return NULL; }
/* * Handle errors raised by SSL I/O functions. NOTE: Not SSL_shutdown ;) * * Arguments: ssl - The SSL object * err - The return code from SSL_get_error * ret - The return code from the SSL I/O function * Returns: None, the calling function should return NULL */ static void handle_ssl_errors(SSL *ssl, int err, int ret) { switch (err) { /* * Strange as it may seem, ZeroReturn is not an error per se. It means * that the SSL Connection has been closed correctly (note, not the * transport layer!), i.e. closure alerts have been exchanged. This is * an exception since * + There's an SSL "error" code for it * + You have to deal with it in any case, close the transport layer * etc */ case SSL_ERROR_ZERO_RETURN: PyErr_SetNone(ssl_ZeroReturnError); break; /* * The WantXYZ exceptions don't mean that there's an error, just that * nothing could be read/written just now, maybe because the transport * layer would block on the operation, or that there's not enough data * available to fill an entire SSL record. */ case SSL_ERROR_WANT_READ: PyErr_SetNone(ssl_WantReadError); break; case SSL_ERROR_WANT_WRITE: PyErr_SetNone(ssl_WantWriteError); break; case SSL_ERROR_WANT_X509_LOOKUP: PyErr_SetNone(ssl_WantX509LookupError); break; case SSL_ERROR_SYSCALL: if (ERR_peek_error() == 0) { if (ret < 0) { syscall_from_errno(); } else { PyObject *v; v = Py_BuildValue("(is)", -1, "Unexpected EOF"); if (v != NULL) { PyErr_SetObject(ssl_SysCallError, v); Py_DECREF(v); } } break; } /* NOTE: Fall-through here, we don't want to duplicate code, right? */ case SSL_ERROR_SSL: ; default: exception_from_error_queue(ssl_Error); break; } }
static PyObject * crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) { exception_from_error_queue(crypto_Error); return NULL; }
/* * Constructor for PKCS12 objects, never called by Python code directly. * The strategy for this object is to create all the Python objects * corresponding to the cert/key/CA certs right away * * Arguments: p12 - A "real" PKCS12 object or NULL * passphrase - Passphrase to use when decrypting the PKCS12 object * Returns: The newly created PKCS12 object */ crypto_PKCS12Obj * crypto_PKCS12_New(PKCS12 *p12, char *passphrase) { crypto_PKCS12Obj *self = NULL; PyObject *cacertobj = NULL; unsigned char *alias_str; int alias_len; X509 *cert = NULL; EVP_PKEY *pkey = NULL; STACK_OF(X509) *cacerts = NULL; int i, cacert_count = 0; /* allocate space for the CA cert stack */ if((cacerts = sk_X509_new_null()) == NULL) { goto error; /* out of memory? */ } /* parse the PKCS12 lump */ if (p12) { if (!PKCS12_parse(p12, passphrase, &pkey, &cert, &cacerts)) { /* * If PKCS12_parse fails, and it allocated cacerts, it seems to * free cacerts, but not re-NULL the pointer. Zounds! Make sure * it is re-set to NULL here, else we'll have a double-free below. */ cacerts = NULL; exception_from_error_queue(crypto_Error); goto error; } else { /* * OpenSSL 1.0.0 sometimes leaves an X509_check_private_key error in * the queue for no particular reason. This error isn't interesting * to anyone outside this function. It's not even interesting to * us. Get rid of it. */ flush_error_queue(); } } if (!(self = PyObject_GC_New(crypto_PKCS12Obj, &crypto_PKCS12_Type))) { goto error; } /* client certificate and friendlyName */ if (cert == NULL) { Py_INCREF(Py_None); self->cert = Py_None; Py_INCREF(Py_None); self->friendlyname = Py_None; } else { if ((self->cert = (PyObject *)crypto_X509_New(cert, 1)) == NULL) { goto error; } /* Now we need to extract the friendlyName of the PKCS12 * that was stored by PKCS_parse() in the alias of the * certificate. */ alias_str = X509_alias_get0(cert, &alias_len); if (alias_str) { self->friendlyname = Py_BuildValue(BYTESTRING_FMT "#", alias_str, alias_len); if (!self->friendlyname) { /* * XXX Untested */ goto error; } /* success */ } else { Py_INCREF(Py_None); self->friendlyname = Py_None; } } /* private key */ if (pkey == NULL) { Py_INCREF(Py_None); self->key = Py_None; } else { if ((self->key = (PyObject *)crypto_PKey_New(pkey, 1)) == NULL) goto error; } /* CA certs */ cacert_count = sk_X509_num(cacerts); if (cacert_count <= 0) { Py_INCREF(Py_None); self->cacerts = Py_None; } else { if ((self->cacerts = PyTuple_New(cacert_count)) == NULL) { goto error; } for (i = 0; i < cacert_count; i++) { cert = sk_X509_value(cacerts, i); if ((cacertobj = (PyObject *)crypto_X509_New(cert, 1)) == NULL) { goto error; } PyTuple_SET_ITEM(self->cacerts, i, cacertobj); } } sk_X509_free(cacerts); /* Don't free the certs, just the container. */ PyObject_GC_Track(self); return self; error: sk_X509_free(cacerts); /* NULL safe. Free just the container. */ if (self) { crypto_PKCS12_clear(self); PyObject_GC_Del(self); } return NULL; }