/*****************************************************************************/ /* */ /* Copyright (c) 2001, 2002, Peter Shannon */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* */ /* * Redistributions of source code must retain the above */ /* copyright notice, this list of conditions and the following */ /* disclaimer. */ /* */ /* * Redistributions in binary form must reproduce the above */ /* copyright notice, this list of conditions and the following */ /* disclaimer in the documentation and/or other materials */ /* provided with the distribution. */ /* */ /* * The name of the contributors may be used to endorse or promote */ /* products derived from this software without specific prior */ /* written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS */ /* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* */ /*****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #ifndef OPENSSL_NO_MD2 #include #endif #include #include #include #include #include // Symmetric ciphers #define DES_ECB 1 #define DES_EDE 2 #define DES_EDE3 3 #define DES_CFB 4 #define DES_EDE_CFB 5 #define DES_EDE3_CFB 6 #define DES_OFB 7 #define DES_EDE_OFB 8 #define DES_EDE3_OFB 9 #define DES_CBC 10 #define DES_EDE_CBC 11 #define DES_EDE3_CBC 12 #define DESX_CBC 13 #define RC4 14 #define RC4_40 15 #define IDEA_ECB 16 #define IDEA_CFB 17 #define IDEA_OFB 18 #define IDEA_CBC 19 #define RC2_ECB 20 #define RC2_CBC 21 #define RC2_40_CBC 22 #define RC2_CFB 23 #define RC2_OFB 24 #define BF_ECB 25 #define BF_CBC 26 #define BF_CFB 27 #define BF_OFB 28 #define CAST5_ECB 29 #define CAST5_CBC 30 #define CAST5_CFB 31 #define CAST5_OFB 32 #define RC5_32_12_16_CBC 33 #define RC5_32_12_16_CFB 34 #define RC5_32_12_16_ECB 35 #define RC5_32_12_16_OFB 36 // SSL connection methods #define SSLV2_SERVER_METHOD 1 #define SSLV2_CLIENT_METHOD 2 #define SSLV2_METHOD 3 #define SSLV3_SERVER_METHOD 4 #define SSLV3_CLIENT_METHOD 5 #define SSLV3_METHOD 6 #define TLSV1_SERVER_METHOD 7 #define TLSV1_CLIENT_METHOD 8 #define TLSV1_METHOD 9 #define SSLV23_SERVER_METHOD 10 #define SSLV23_CLIENT_METHOD 11 #define SSLV23_METHOD 12 // SSL connection states // PEM encoded data types #define RSA_PUBLIC_KEY 1 #define RSA_PRIVATE_KEY 2 #define DSA_PUBLIC_KEY 3 #define DSA_PRIVATE_KEY 4 #define DH_PUBLIC_KEY 5 #define DH_PRIVATE_KEY 6 #define X509_CERTIFICATE 7 #define X_X509_CRL 8 // X509_CRL already used by OpenSSL library #define CMS_MESSAGE 9 // Asymmetric ciphers #define RSA_CIPHER 1 #define DSA_CIPHER 2 #define DH_CIPHER 3 //#define NO_DSA //#define NO_DH // Digests #ifndef OPENSSL_NO_MD2 #define MD2_DIGEST 1 #endif #define MD5_DIGEST 2 #define SHA_DIGEST 3 #define SHA1_DIGEST 4 #define RIPEMD160_DIGEST 5 #define SHA256_DIGEST 6 #define SHA384_DIGEST 7 #define SHA512_DIGEST 8 // Object format #define SHORTNAME_FORMAT 1 #define LONGNAME_FORMAT 2 // Output format #define PEM_FORMAT 1 #define DER_FORMAT 2 // Object check functions #define X_X509_Check(op) ((op)->ob_type == &x509type) #define X_X509_store_Check(op) ((op)->ob_type == &x509_storetype) #define X_X509_crl_Check(op) ((op)->ob_type == &x509_crltype) #define X_X509_revoked_Check(op) ((op)->ob_type == &x509_revokedtype) #define X_asymmetric_Check(op) ((op)->ob_type == &asymmetrictype) #define X_symmetric_Check(op) ((op)->ob_type == &symmetrictype) #define X_digest_Check(op) ((op)->ob_type == &digesttype) #define X_hmac_Check(op) ((op)->ob_type == &hmactype) #define X_ssl_Check(op) ((op)->ob_type == &ssltype) #define X_cms_Check(op) ((op)->ob_type == &cmstype) // Symbolic representation of "no SSL shutdown mode requested" #define SSL_NO_SHUTDOWN 0 static char pow_module__doc__ [] = "\n" "
\n" " POW\n" " Peter Shannon\n" "
\n" " \n" " \n" " This third major release of POW addresses the most critical missing\n" " parts of functionality, X509v3 support. Initially I thought adding\n" " support via the OpenSSL code would be the easiest option but this\n" " proved to be incorrect mainly due to the way I have chosen to handle\n" " the complex data such as directoryNames and\n" " generalNames. It is easier in python to\n" " construct complex sets of data using lists and dictionaries than\n" " coordinate large numbers of objects and method calls. This is no\n" " criticism, it is just extremely easy. Coding complex data such as the\n" " certificatePolicies coding coding routines in C\n" " to handle the data proved laborous and ultimately error prone.\n" " \n" " \n" " PKIX structures are supported by a few operations on the relevant POW\n" " objects and through a Python library which is modelled on the DER\n" " encoding rules. Modeling DER does expose some of the complexities of\n" " the ASN1 specifications but avoids coding many assumptions into the\n" " data structures and the interface for the objects. For an example of\n" " overly complex definitions take a look at the\n" " Name object in RFC3280. It is equally\n" " important that modeling DER in the way leads to a library which is\n" " trivial to extend to support new objects - simple objects are one\n" " liners and complex objects only require the definition of a new\n" " constructor.\n" " \n" " \n" " functionality have been plugged. The Ssl class has received\n" " several new features relating to security. Other areas have been\n" " improved: PRNG support, certificate and CRL signing, certificate chain\n" " and client verification. Many bugs have been fixed, and certain\n" " parts of code re-written where necessary. I hope you enjoy using POW\n" " and please feel free to send me feature requests and bug reports.\n" " \n" " \n" "
\n" ; /*========== Pre-definitions ==========*/ static PyObject *ErrorObject, *SSLErrorObject, *ZeroReturnErrorObject, *WantReadErrorObject, *WantWriteErrorObject, *SSLSyscallErrorObject, *SSLErrorSSLErrorObject, *SSLSyscallSSLErrorObject, *SSLUnexpectedEOFErrorObject, *SSLOtherErrorObject; static PyTypeObject x509type, x509_storetype, x509_crltype, x509_revokedtype, asymmetrictype, symmetrictype, digesttype, hmactype, ssltype, cmstype; /*========== Pre-definitions ==========*/ /*========== C structs ==========*/ typedef struct { PyObject_HEAD X509 *x509; } x509_object; typedef struct { PyObject_HEAD X509_STORE *store; } x509_store_object; typedef struct { PyObject_HEAD X509_CRL *crl; } x509_crl_object; typedef struct { PyObject_HEAD X509_REVOKED *revoked; } x509_revoked_object; typedef struct { PyObject_HEAD void *cipher; int key_type; int cipher_type; } asymmetric_object; typedef struct { PyObject_HEAD EVP_CIPHER_CTX cipher_ctx; int cipher_type; } symmetric_object; typedef struct { PyObject_HEAD EVP_MD_CTX digest_ctx; int digest_type; } digest_object; typedef struct { PyObject_HEAD HMAC_CTX hmac_ctx; } hmac_object; typedef struct { PyObject_HEAD int ctxset; SSL *ssl; SSL_CTX *ctx; STACK_OF(X509) *trusted_certs; char *x509_cb_err; } ssl_object; typedef struct { PyObject_HEAD CMS_ContentInfo *cms; } cms_object; /*========== C structs ==========*/ /*========== helper functions ==========*/ /* * Minimal intervention debug-by-printf() hack, use only for good. */ #if 0 #define KVETCH(_msg_) write(2, _msg_ "\n", sizeof(_msg_)) #else #define KVETCH(_msg_) #endif /* * Error handling macros. These macros make two assumptions: * * 1) All the macros assume that there's a cleanup label named * "error" which these macros can use as a goto target. * * 2) assert_no_unhandled_openssl_errors() assumes that the return * value is stored in a PyObject* variable named "result". * * These are icky assumptions, but they make it easier to provide * uniform error handling and make the code easier to read, not to * mention making it easier to track down obscure OpenSSL errors. */ #define lose(_msg_) \ do { \ PyErr_SetString(ErrorObject, (_msg_)); \ goto error; \ } while (0) #define lose_type_error(_msg_) \ do { \ PyErr_SetString(PyExc_TypeError, (_msg_)); \ goto error; \ } while (0) #define lose_openssl_error(_msg_) \ do { \ set_openssl_exception(ErrorObject, (_msg_)); \ goto error; \ } while (0) #define lose_ssl_error(_self_, _code_) \ do { \ set_openssl_ssl_exception(_self_, _code_); \ goto error; \ } while (0) #define assert_no_unhandled_openssl_errors() \ do { \ if (ERR_peek_error()) { \ if (result) { \ Py_XDECREF(result); \ result = NULL; \ } \ lose_openssl_error(assert_helper(__LINE__)); \ } \ } while (0) static char * assert_helper(int line) { static const char fmt[] = "Unhandled OpenSSL error at " __FILE__ ":%d!"; static char msg[sizeof(fmt) + 10]; snprintf(msg, sizeof(msg), fmt, line); return msg; } static int docset_helper_add(PyObject *set, char *v) { PyObject *value = NULL; if ((value = PyString_FromString(v)) == NULL) lose("could not allocate memory"); if (PyList_Append(set, value) != 0) goto error; Py_XDECREF(value); return 1; error: Py_XDECREF(value); return 0; } /* * Generate an encrypion envelope. Saves a lot of space having this case * statement in one place. */ static const EVP_CIPHER * evp_cipher_factory(int cipher_type) { switch(cipher_type) { #ifndef OPENSSL_NO_DES case DES_ECB: return EVP_des_ecb(); case DES_EDE: return EVP_des_ede(); case DES_EDE3: return EVP_des_ede3(); case DES_CFB: return EVP_des_cfb(); case DES_EDE_CFB: return EVP_des_ede_cfb(); case DES_EDE3_CFB: return EVP_des_ede3_cfb(); case DES_OFB: return EVP_des_ofb(); case DES_EDE_OFB: return EVP_des_ede_ofb(); case DES_EDE3_OFB: return EVP_des_ede3_ofb(); case DES_CBC: return EVP_des_cbc(); case DES_EDE_CBC: return EVP_des_ede_cbc(); case DES_EDE3_CBC: return EVP_des_ede3_cbc(); case DESX_CBC: return EVP_desx_cbc(); #endif #ifndef OPENSSL_NO_RC4 case RC4: return EVP_rc4(); case RC4_40: return EVP_rc4_40(); #endif #ifndef OPENSSL_NO_IDEA case IDEA_ECB: return EVP_idea_ecb(); case IDEA_CFB: return EVP_idea_cfb(); case IDEA_OFB: return EVP_idea_ofb(); case IDEA_CBC: return EVP_idea_cbc(); #endif #ifndef OPENSSL_NO_RC2 case RC2_ECB: return EVP_rc2_ecb(); case RC2_CBC: return EVP_rc2_cbc(); case RC2_40_CBC: return EVP_rc2_40_cbc(); case RC2_CFB: return EVP_rc2_cfb(); case RC2_OFB: return EVP_rc2_ofb(); #endif #ifndef OPENSSL_NO_BF case BF_ECB: return EVP_bf_ecb(); case BF_CBC: return EVP_bf_cbc(); case BF_CFB: return EVP_bf_cfb(); case BF_OFB: return EVP_bf_ofb(); #endif #ifndef OPENSSL_NO_CAST5 case CAST5_ECB: return EVP_cast5_ecb(); case CAST5_CBC: return EVP_cast5_cbc(); case CAST5_CFB: return EVP_cast5_cfb(); case CAST5_OFB: return EVP_cast5_ofb(); #endif #ifndef OPENSSL_NO_RC5 case RC5_32_12_16_CBC: return EVP_rc5_32_12_16_cbc(); case RC5_32_12_16_CFB: return EVP_rc5_32_12_16_cfb(); case RC5_32_12_16_ECB: return EVP_rc5_32_12_16_ecb(); case RC5_32_12_16_OFB: return EVP_rc5_32_12_16_ofb(); #endif default: return NULL; } } /* * Raise an exception with data pulled from the OpenSSL error stack. * Exception value is a tuple with some internal structure. If a * string error message is supplied, that string is the first element * of the exception value tuple. Remainder of exception value tuple * is zero or more tuples, each representing one error from the stack. * Each error tuple contains six slots: * - the numeric error code * - string translation of numeric error code ("reason") * - name of library in which error occurred * - name of function in which error occurred * - name of file in which error occurred * - line number in file where error occurred */ static void set_openssl_exception(PyObject *error_class, const char *msg) { PyObject *errors; unsigned long err; const char *file; int line; errors = PyList_New(0); if (msg) { PyObject *s = Py_BuildValue("s", msg); (void) PyList_Append(errors, s); Py_XDECREF(s); } while ((err = ERR_get_error_line(&file, &line)) != 0) { PyObject *t = Py_BuildValue("(issssi)", err, ERR_reason_error_string(err), ERR_lib_error_string(err), ERR_func_error_string(err), file, line); (void) PyList_Append(errors, t); Py_XDECREF(t); } PyErr_SetObject(error_class, PyList_AsTuple(errors)); Py_XDECREF(errors); } static void set_openssl_ssl_exception(const ssl_object *self, const int ret) { int err = SSL_get_error(self->ssl, ret); const char *s = NULL; switch(err) { /* * These three get their own exceptions. */ case SSL_ERROR_ZERO_RETURN: PyErr_SetNone(ZeroReturnErrorObject); break; case SSL_ERROR_WANT_READ: PyErr_SetNone(WantReadErrorObject); break; case SSL_ERROR_WANT_WRITE: PyErr_SetNone(WantWriteErrorObject); break; case SSL_ERROR_SYSCALL: /* * Horrible jumbled mess of I/O related errors. I'd ask what they * were thinking, except that it's pretty clear that they weren't. */ if (ERR_peek_error()) set_openssl_exception(SSLSyscallSSLErrorObject, NULL); else if (ret) PyErr_SetFromErrno(SSLSyscallErrorObject); else PyErr_SetNone(SSLUnexpectedEOFErrorObject); break; case SSL_ERROR_SSL: /* * Generic OpenSSL error during an SSL call. I think. */ set_openssl_exception(SSLErrorSSLErrorObject, self->x509_cb_err); break; /* * All other SSL errors are returned as a (number, string) tuple. */ case SSL_ERROR_NONE: s = "SSL_ERROR_NONE"; break; case SSL_ERROR_WANT_X509_LOOKUP: s = "SSL_ERROR_WANT_X509_LOOKUP"; break; case SSL_ERROR_WANT_CONNECT: s = "SSL_ERROR_WANT_CONNECT"; break; case SSL_ERROR_WANT_ACCEPT: s = "SSL_ERROR_WANT_ACCEPT"; break; default: s = "UNKNOWN_SSL_ERROR"; } if (s) PyErr_SetObject(SSLOtherErrorObject, Py_BuildValue("(is)", err, s)); } static PyObject * X509_object_helper_set_name(X509_NAME *name, PyObject *name_sequence) { PyObject *pair = NULL; PyObject *type = NULL; PyObject *value = NULL; int no_pairs = 0, i = 0, str_type = 0, nid; unsigned char *valueptr = NULL; char *typeptr = NULL; no_pairs = PySequence_Size(name_sequence); for (i = 0; i < no_pairs; i++) { if ((pair = PySequence_GetItem(name_sequence, i)) == NULL) return NULL; if (!PyTuple_Check(pair) && !PyList_Check(pair)) lose_type_error("inapropriate type"); if (PySequence_Size(pair) != 2) lose("each name entry must have 2 elements"); if ((type = PySequence_GetItem(pair, 0)) == NULL) lose_type_error("could not get type string"); if (!PyString_Check(type)) lose_type_error("inapropriate type"); if ((value = PySequence_GetItem(pair, 1)) == NULL) lose_type_error("could not get value string"); if (!PyString_Check(value)) lose_type_error("inapropriate type"); typeptr = PyString_AsString(type); valueptr = (unsigned char *) PyString_AsString(value); str_type = ASN1_PRINTABLE_type(valueptr, -1); if ((nid = OBJ_ln2nid(typeptr)) == 0 && (nid = OBJ_sn2nid(typeptr)) == 0) lose("unknown ASN1 object"); if (!X509_NAME_add_entry_by_NID(name, nid, str_type, valueptr, strlen((char *) valueptr), -1, 0)) lose("unable to add name entry"); Py_XDECREF(pair); Py_XDECREF(type); Py_XDECREF(value); pair = NULL; type = NULL; value = NULL; } return name_sequence; error: Py_XDECREF(pair); Py_XDECREF(type); Py_XDECREF(value); return NULL; } static PyObject * X509_object_helper_get_name(X509_NAME *name, int format) { int no_entries = 0, no_pairs = 0, i = 0, j = 0, value_len = 0, nid = 0; X509_NAME_ENTRY *entry = NULL; char *value = NULL, long_name[512]; const char *short_name; PyObject *result_list = NULL; PyObject *pair = NULL; PyObject *py_type = NULL; PyObject *py_value = NULL; no_entries = X509_NAME_entry_count(name); if ((result_list = PyTuple_New(no_entries)) == NULL) lose("could not allocate memory"); for(i = 0; i < no_entries; i++) { if ((entry = X509_NAME_get_entry(name, i)) == NULL) lose("could not get certificate name"); if (entry->value->length + 1 > value_len) { if (value) free(value); if ((value = malloc(entry->value->length + 1)) == NULL) lose("could not allocate memory"); value_len = entry->value->length + 1; } memcpy(value, entry->value->data, entry->value->length); value[entry->value->length] = 0; if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) lose("could not find object name"); switch (format) { case SHORTNAME_FORMAT: nid = OBJ_ln2nid(long_name); short_name = OBJ_nid2sn(nid); py_type = PyString_FromString(short_name); break; case LONGNAME_FORMAT: py_type = PyString_FromString(long_name); break; default: lose("unknown name format"); } py_value = PyString_FromString(value); if ((pair = PyTuple_New(2)) == NULL) lose("could not allocate memory"); PyTuple_SetItem(pair, 0, py_type); PyTuple_SetItem(pair, 1, py_value); PyTuple_SetItem(result_list, i, pair); } if (value) free(value); return result_list; error: if (value) free(value); if (result_list) { no_pairs = PyTuple_Size(result_list); for (i = 0; i < no_pairs; i++) { pair = PyTuple_GetItem(result_list, i); no_entries = PyTuple_Size(result_list); for (j = 0; j < no_entries; j++) { py_value = PyTuple_GetItem(pair, i); Py_XDECREF(py_value); } } } Py_XDECREF(py_type); Py_XDECREF(py_value); Py_XDECREF(result_list); return NULL; } static STACK_OF(X509) * x509_helper_sequence_to_stack(PyObject *x509_sequence) { x509_object *x509obj = NULL; STACK_OF(X509) *x509_stack = NULL; int size = 0, i = 0; if (x509_sequence != Py_None && !PyTuple_Check(x509_sequence) && !PyList_Check(x509_sequence)) lose_type_error("Inapropriate type"); if ((x509_stack = sk_X509_new_null()) == NULL) lose("Couldn't create new X509 stack"); if (x509_sequence != Py_None) { size = PySequence_Size(x509_sequence); for (i = 0; i < size; i++) { if ((x509obj = (x509_object*) PySequence_GetItem(x509_sequence, i)) == NULL) goto error; if (!X_X509_Check(x509obj)) lose_type_error("Inapropriate type"); if (!sk_X509_push(x509_stack, x509obj->x509)) lose("Couldn't add X509 object to stack"); Py_XDECREF(x509obj); x509obj = NULL; } } return x509_stack; error: if (x509_stack) sk_X509_free(x509_stack); Py_XDECREF(x509obj); return NULL; } static PyObject * stack_to_tuple_helper(_STACK *sk, PyObject *(*handler)(void *)) { PyObject *result_list = NULL, *result_tuple = NULL, *obj = NULL; if ((result_list = PyList_New(0)) == NULL) lose("could not allocate memory"); while (sk_num(sk)) { if ((obj = handler(sk_value(sk, 0))) == NULL) lose("could not allocate memory"); sk_shift(sk); if (PyList_Append(result_list, obj) != 0) goto error; Py_XDECREF(obj); obj = NULL; } result_tuple = PyList_AsTuple(result_list); Py_XDECREF(result_list); return result_tuple; error: Py_XDECREF(obj); Py_XDECREF(result_list); return NULL; } /* * Time conversion functions. These follow RFC 5280, but use a single * text encoding that looks like GeneralizedTime as restricted by RFC * 5280; conversion to and from UTCTime is handled internally * according to the RFC 5280 rules. The intent is to hide the * horrible short-sighted mess from Python code entirely. */ static PyObject * ASN1_TIME_to_Python(ASN1_TIME *t) { ASN1_GENERALIZEDTIME *g = ASN1_TIME_to_generalizedtime(t, NULL); PyObject *result = NULL; if (g) { result = Py_BuildValue("s", g->data); ASN1_GENERALIZEDTIME_free(g); } return result; } static int python_ASN1_TIME_set_string(ASN1_TIME *t, const char *s) { if (t == NULL || s == NULL || strlen(s) < 10) return 0; if ((s[0] == '1' && s[1] == '9' && s[2] > '4') || (s[0] == '2' && s[1] == '0' && s[2] < '5')) return ASN1_UTCTIME_set_string(t, s + 2); else return ASN1_GENERALIZEDTIME_set_string(t, s); } /*========== helper funcitons ==========*/ /*========== X509 code ==========*/ static x509_object * X509_object_new(void) { x509_object *self; self = PyObject_New(x509_object, &x509type); if (self == NULL) goto error; self->x509 = X509_new(); return self; error: Py_XDECREF(self); return NULL; } /* * This function is pretty dumb. Most of the work is done by the module * function pow_module_pem_read(). */ static x509_object * X509_object_pem_read(BIO *in) { x509_object *self; if ((self = PyObject_New(x509_object, &x509type)) == NULL) goto error; if ((self->x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) lose("could not load PEM encoded certificate"); return self; error: Py_XDECREF(self); return NULL; } static x509_object * X509_object_der_read(unsigned char *src, int len) { x509_object *self; unsigned char *ptr = src; if ((self = PyObject_New(x509_object, &x509type)) == NULL) goto error; self->x509 = X509_new(); if(!d2i_X509(&self->x509, (const unsigned char **) &ptr, len)) lose("could not load PEM encoded certificate"); return self; error: Py_XDECREF(self); return NULL; } /* * Unlike the previous function this creates the BIO itself. The BIO_s_mem * is used as a buffer which the certificate is read into, from this buffer * it is read into a char[] and returned as a string. */ static PyObject * X509_object_write_helper(x509_object *self, PyObject *args, int format) { int len = 0; char *buf = NULL; BIO *out_bio = NULL; PyObject *cert = NULL; if (!PyArg_ParseTuple(args, "")) return NULL; out_bio = BIO_new(BIO_s_mem()); switch (format) { case DER_FORMAT: if (!i2d_X509_bio(out_bio, self->x509)) lose("unable to write certificate"); break; case PEM_FORMAT: if (!PEM_write_bio_X509(out_bio, self->x509)) lose("unable to write certificate"); break; default: lose("internal error, unknown output format"); } if ((len = BIO_ctrl_pending(out_bio)) == 0) lose("unable to get bytes stored in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if (BIO_read(out_bio, buf, len) != len) lose("unable to write out cert"); cert = Py_BuildValue("s#", buf, len); BIO_free(out_bio); free(buf); return cert; error: if (out_bio) BIO_free(out_bio); if (buf) free(buf); Py_XDECREF(cert); return NULL; } static char X509_object_pem_write__doc__[] = "\n" "
\n" " X509\n" " pemWrite\n" "
\n" " \n" " \n" " This method returns a PEM encoded certificate as a\n" " string.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_pem_write(x509_object *self, PyObject *args) { return X509_object_write_helper(self, args, PEM_FORMAT); } static char X509_object_der_write__doc__[] = "\n" "
\n" " X509\n" " derWrite\n" "
\n" " \n" " \n" " This method returns a DER encoded certificate as a\n" " string.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_der_write(x509_object *self, PyObject *args) { return X509_object_write_helper(self, args, DER_FORMAT); } /* * Currently this function only supports RSA keys. */ static char X509_object_set_public_key__doc__[] = "\n" "
\n" " X509\n" " setPublicKey\n" " key\n" "
\n" " \n" " \n" " This method sets the public key for this certificate object. The\n" " parameter key should be an instance of\n" " Asymmetric containing a public key.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_public_key(x509_object *self, PyObject *args) { EVP_PKEY *pkey = NULL; asymmetric_object *asym; if (!PyArg_ParseTuple(args, "O!", &asymmetrictype, &asym)) goto error; if ((pkey = EVP_PKEY_new()) == NULL) lose("could not allocate memory"); if (!EVP_PKEY_assign_RSA(pkey, asym->cipher)) lose("EVP_PKEY assignment error"); if (!X509_set_pubkey(self->x509,pkey)) lose("could not set certificate's public key"); Py_RETURN_NONE; error: if (pkey) EVP_PKEY_free(pkey); return NULL; } static char X509_object_sign__doc__[] = "\n" "
\n" " X509\n" " sign\n" " key\n" " digest = MD5_DIGEST\n" "
\n" " \n" " \n" " This method signs a certificate with a private key. See the\n" " example for the methods which should be invoked before signing a\n" " certificate. key should be an instance of\n" " Asymmetric containing a private key.\n" " The optional parameter digest indicates\n" " which digest function should be used to compute the hash to be\n" " signed, it should be one of the following:\n" " \n" " \n" #ifndef OPENSSL_NO_MD2 " MD2_DIGEST\n" #endif " MD5_DIGEST\n" " SHA_DIGEST\n" " SHA1_DIGEST\n" " RIPEMD160_DIGEST\n" " SHA256_DIGEST\n" " SHA384_DIGEST\n" " SHA512_DIGEST\n" " \n" " \n" "
\n" ; static PyObject * X509_object_sign(x509_object *self, PyObject *args) { EVP_PKEY *pkey = NULL; asymmetric_object *asym; int digest = MD5_DIGEST; if (!PyArg_ParseTuple(args, "O!|i", &asymmetrictype, &asym, &digest)) goto error; if ((pkey = EVP_PKEY_new()) == NULL) lose("could not allocate memory"); if (asym->key_type != RSA_PRIVATE_KEY) lose("cannot use this type of key"); if (!EVP_PKEY_assign_RSA(pkey, asym->cipher)) lose("EVP_PKEY assignment error"); switch (digest) { case MD5_DIGEST: if (!X509_sign(self->x509, pkey, EVP_md5())) lose("could not sign certificate"); break; #ifndef OPENSSL_NO_MD2 case MD2_DIGEST: if (!X509_sign(self->x509, pkey, EVP_md2())) lose("could not sign certificate"); break; #endif case SHA_DIGEST: if (!X509_sign(self->x509, pkey, EVP_sha())) lose("could not sign certificate"); break; case SHA1_DIGEST: if (!X509_sign(self->x509, pkey, EVP_sha1())) lose("could not sign certificate"); break; case RIPEMD160_DIGEST: if (!X509_sign(self->x509, pkey, EVP_ripemd160())) lose("could not sign certificate"); break; case SHA256_DIGEST: if (!X509_sign(self->x509, pkey, EVP_sha256())) lose("could not sign certificate"); break; case SHA384_DIGEST: if (!X509_sign(self->x509, pkey, EVP_sha384())) lose("could not sign certificate"); break; case SHA512_DIGEST: if (!X509_sign(self->x509, pkey, EVP_sha512())) lose("could not sign certificate"); break; } Py_RETURN_NONE; error: if (pkey) EVP_PKEY_free(pkey); return NULL; } static char X509_object_get_version__doc__[] = "\n" "
\n" " X509\n" " getVersion\n" "
\n" " \n" " \n" " This method returns the version number from the version field of\n" " this certificate.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_version(x509_object *self, PyObject *args) { long version = 0; if (!PyArg_ParseTuple(args, "")) goto error; version = X509_get_version(self->x509); return Py_BuildValue("l", version); error: return NULL; } static char X509_object_set_version__doc__[] = "\n" "
\n" " X509\n" " setVersion\n" " version\n" "
\n" " \n" " \n" " This method sets the version number in the version field of\n" " this certificate. version should be an\n" " integer.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_version(x509_object *self, PyObject *args) { long version = 0; if (!PyArg_ParseTuple(args, "l", &version)) goto error; if (!X509_set_version(self->x509, version)) lose("could not set certificate version"); Py_RETURN_NONE; error: return NULL; } static char X509_object_get_serial__doc__[] = "\n" "
\n" " X509\n" " getSerial\n" "
\n" " \n" " \n" " This method get the serial number in the serial field of\n" " this certificate.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_serial(x509_object *self, PyObject *args) { long serial = 0; ASN1_INTEGER *asn1i = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if ((asn1i = X509_get_serialNumber(self->x509)) == NULL) lose("could not get serial number"); if ((serial = ASN1_INTEGER_get(asn1i)) == -1) lose("could not convert ASN1 Integer to long"); return Py_BuildValue("l", serial); error: return NULL; } static char X509_object_set_serial__doc__[] = "\n" "
\n" " X509\n" " setSerial\n" " serial\n" "
\n" " \n" " \n" " This method sets the serial number in the serial field of\n" " this certificate. serial should ba an\n" " integer.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_serial(x509_object *self, PyObject *args) { long serial = 0; ASN1_INTEGER *asn1i = NULL; if (!PyArg_ParseTuple(args, "l", &serial)) goto error; if ((asn1i = ASN1_INTEGER_new()) == NULL) lose("could not allocate memory"); if (!ASN1_INTEGER_set(asn1i, serial)) lose("could not set ASN1 integer"); if (!X509_set_serialNumber(self->x509, asn1i)) lose("could not set certificate serial"); ASN1_INTEGER_free(asn1i); Py_RETURN_NONE; error: if (asn1i) ASN1_INTEGER_free(asn1i); return NULL; } static char X509_object_get_issuer__doc__[] = "\n" "
\n" " X509\n" " getIssuer\n" " format = SHORTNAME_FORMAT\n" "
\n" " \n" " \n" " This method returns a tuple containing the issuers name. Each\n" " element of the tuple is a tuple with 2 elements. The first tuple\n" " is an object name and the second is it's value. Both issuer and\n" " subject are names distinguished normally composed of a small\n" " number of objects:\n" " \n" " \n" " c or countryName\n" " st or stateOrProvinceName\n" " o or organizationName\n" " l or localityName\n" " ou or organizationalUnitName\n" " cn or commonName\n" " \n" " \n" " The data type varies from one object to another, however, all the\n" " common objects are strings. It would be possible to specify any\n" " kind of object but that would certainly adversely effect\n" " portability and is not recommended.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_issuer(x509_object *self, PyObject *args) { PyObject *result_list = NULL; X509_NAME *name = NULL; int format = SHORTNAME_FORMAT; if (!PyArg_ParseTuple(args, "|i", &format)) goto error; if ((name = X509_get_issuer_name(self->x509)) == NULL) lose("could not get issuers name"); if ((result_list = X509_object_helper_get_name(name, format)) == NULL) lose("failed to produce name list"); return result_list; error: return NULL; } static char X509_object_get_subject__doc__[] = "\n" "
\n" " X509\n" " getSubject\n" " format = SHORTNAME_FORMAT\n" "
\n" " \n" " \n" " This method returns a tuple containing the subjects name. See\n" " getIssuer for a description of the returned\n" " object's format.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_subject(x509_object *self, PyObject *args) { PyObject *result_list = NULL; X509_NAME *name = NULL; int format = SHORTNAME_FORMAT; if (!PyArg_ParseTuple(args, "|i", &format)) goto error; if ((name = X509_get_subject_name(self->x509)) == NULL) lose("could not get issuers name"); if ((result_list = X509_object_helper_get_name(name, format)) == NULL) lose("failed to produce name list"); return result_list; error: return NULL; } static char X509_object_set_subject__doc__[] = "\n" "
\n" " X509\n" " setSubject\n" " name\n" "
\n" " \n" " \n" " This method is used to set the subjects name.\n" " name can be comprised of lists or tuples in\n" " the format described in the getIssuer method.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_subject(x509_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PyTuple_Check(name_sequence) && !PyList_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = X509_NAME_new()) == NULL) lose("could not allocate memory"); if (!X509_object_helper_set_name(name, name_sequence)) lose("unable to set new name"); if (!X509_set_subject_name(self->x509, name)) lose("unable to set name"); X509_NAME_free(name); Py_RETURN_NONE; error: return NULL; } static char X509_object_set_issuer__doc__[] = "\n" "
\n" " X509\n" " setIssuer\n" " name\n" "
\n" " \n" " \n" " This method is used to set the issuers name.\n" " name can be comprised of lists or tuples in\n" " the format described in the getissuer method.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_issuer(x509_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PyTuple_Check(name_sequence) && !PyList_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = X509_NAME_new()) == NULL) lose("could not allocate memory"); if (!X509_object_helper_set_name(name, name_sequence)) lose("unable to set new name"); if (!X509_set_issuer_name(self->x509,name)) lose("unable to set name"); X509_NAME_free(name); Py_RETURN_NONE; error: if (name) X509_NAME_free(name); return NULL; } static char X509_object_get_not_before__doc__[] = "\n" "
\n" " X509\n" " getNotBefore\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this function returns a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_not_before (x509_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return ASN1_TIME_to_Python(self->x509->cert_info->validity->notBefore); error: return NULL; } static char X509_object_get_not_after__doc__[] = "\n" "
\n" " X509\n" " getNotAfter\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this function returns a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_not_after (x509_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return ASN1_TIME_to_Python(self->x509->cert_info->validity->notAfter); error: return NULL; } static char X509_object_set_not_after__doc__[] = "\n" "
\n" " X509\n" " setNotAfter\n" " time\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this accepts one parameter, a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_not_after (x509_object *self, PyObject *args) { char *new_time = NULL; if (!PyArg_ParseTuple(args, "s", &new_time)) goto error; if (!python_ASN1_TIME_set_string(self->x509->cert_info->validity->notAfter, new_time)) lose("Could not set notAfter"); Py_RETURN_NONE; error: return NULL; } static char X509_object_set_not_before__doc__[] = "\n" "
\n" " X509\n" " setNotBefore\n" " time\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this accepts one parameter, a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_set_not_before (x509_object *self, PyObject *args) { char *new_time = NULL; if (!PyArg_ParseTuple(args, "s", &new_time)) goto error; if (!python_ASN1_TIME_set_string(self->x509->cert_info->validity->notBefore, new_time)) lose("Could not set notBefore"); Py_RETURN_NONE; error: return NULL; } static char X509_object_add_extension__doc__[] = "\n" "
\n" " X509\n" " addExtension\n" " extensionName\n" " critical\n" " extensionValue\n" "
\n" " \n" " \n" " This method adds an extension to this certificate.\n" " extensionName should be the of the\n" " extension. critical should an integer, 1\n" " for true and 0 for false. extensionValue\n" " should be a string, DER encoded value of the extension. The name\n" " of the extension must be correct according to OpenSSL and can be\n" " checked in the objects.h header file, part of\n" " the OpenSSL source distribution. In the majority of cases they\n" " are the same as those defined in POW._oids\n" " but if you do encounter problems is may be worth checking.\n" " \n" " \n" " <function>addExtension</function> method usage\n" " \n" " basic = POW.pkix.BasicConstraints()\n" " basic.set([1,5])\n" " serverCert.addExtension('basicConstraints', 0, basic.toString())\n" " \n" " \n" " \n" "
\n" ; static PyObject * X509_object_add_extension(x509_object *self, PyObject *args) { int critical = 0, nid = 0, len = 0; char *name = NULL; unsigned char *buf = NULL; ASN1_OCTET_STRING *octetString = NULL; X509_EXTENSION *extn = NULL; if (!PyArg_ParseTuple(args, "sis#", &name, &critical, &buf, &len)) goto error; if ((octetString = M_ASN1_OCTET_STRING_new()) == NULL) lose("could not allocate memory"); if (!ASN1_OCTET_STRING_set(octetString, buf, len)) lose("could not set ASN1 Octect string"); if ((nid = OBJ_txt2nid(name)) == NID_undef) lose("extension has unknown object identifier"); if ((extn = X509_EXTENSION_create_by_NID(NULL, nid, critical, octetString)) == NULL) lose("unable to create ASN1 X509 Extension object"); if (!self->x509->cert_info->extensions && (self->x509->cert_info->extensions = sk_X509_EXTENSION_new_null()) == NULL) lose("unable to allocate memory"); if (!sk_X509_EXTENSION_push(self->x509->cert_info->extensions, extn)) lose("unable to add extension"); Py_RETURN_NONE; error: if (extn) X509_EXTENSION_free(extn); return NULL; } static char X509_object_clear_extensions__doc__[] = "\n" "
\n" " X509\n" " clearExtensions\n" "
\n" " \n" " \n" " This method clears the structure which holds the extension for\n" " this certificate.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_clear_extensions(x509_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; if (self->x509->cert_info->extensions) { sk_X509_EXTENSION_free(self->x509->cert_info->extensions); self->x509->cert_info->extensions = NULL; } Py_RETURN_NONE; error: return NULL; } static char X509_object_count_extensions__doc__[] = "\n" "
\n" " X509\n" " countExtensions\n" "
\n" " \n" " \n" " This method returns the size of the structure which holds the\n" " extension for this certificate.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_count_extensions(x509_object *self, PyObject *args) { int num = 0; if (!PyArg_ParseTuple(args, "")) goto error; if (self->x509->cert_info->extensions) num = sk_X509_EXTENSION_num(self->x509->cert_info->extensions); return Py_BuildValue("i", num); error: return NULL; } static char X509_object_get_extension__doc__[] = "\n" "
\n" " X509\n" " getExtension\n" " index\n" "
\n" " \n" " \n" " This method returns a tuple equivalent the parameters of\n" " addExtension.\n" " \n" " \n" "
\n" ; static PyObject * X509_object_get_extension(x509_object *self, PyObject *args) { int num = 0, index = 0, ext_nid = 0; char const *ext_ln = NULL; char unknown_ext [] = "unknown"; X509_EXTENSION *ext; if (!PyArg_ParseTuple(args, "i", &index)) goto error; if (self->x509->cert_info->extensions) num = sk_X509_EXTENSION_num(self->x509->cert_info->extensions); if (index >= num) lose("certificate does not have that many extensions"); if ((ext = sk_X509_EXTENSION_value(self->x509->cert_info->extensions, index)) == NULL) lose("could not get extension"); if ((ext_nid = OBJ_obj2nid(ext->object)) == NID_undef) lose("extension has unknown object identifier"); if ((ext_ln = OBJ_nid2sn(ext_nid)) == NULL) ext_ln = unknown_ext; return Py_BuildValue("sis#", ext_ln, ext->critical, ext->value->data, ext->value->length); error: return NULL; } static char x509_object_pprint__doc__[] = "\n" "
\n" " X509\n" " pprint\n" "
\n" " \n" " \n" " This method returns a formatted string showing the information\n" " held in the certificate.\n" " \n" " \n" "
\n" ; static PyObject * x509_object_pprint(x509_object *self, PyObject *args) { int len = 0, ret = 0; char *buf = NULL; BIO *out_bio = NULL; PyObject *cert = NULL; if (!PyArg_ParseTuple(args, "")) goto error; out_bio = BIO_new(BIO_s_mem()); if (!X509_print(out_bio, self->x509)) lose("unable to write crl"); if ((len = BIO_ctrl_pending(out_bio)) == 0) lose("unable to get bytes stored in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if ((ret = BIO_read(out_bio, buf, len)) != len) lose("unable to write out cert"); cert = Py_BuildValue("s#", buf, len); BIO_free(out_bio); free(buf); return cert; error: if (out_bio) BIO_free(out_bio); if (buf) free(buf); return NULL; } static struct PyMethodDef X509_object_methods[] = { {"pemWrite", (PyCFunction)X509_object_pem_write, METH_VARARGS, NULL}, {"derWrite", (PyCFunction)X509_object_der_write, METH_VARARGS, NULL}, {"sign", (PyCFunction)X509_object_sign, METH_VARARGS, NULL}, {"setPublicKey", (PyCFunction)X509_object_set_public_key, METH_VARARGS, NULL}, {"getVersion", (PyCFunction)X509_object_get_version, METH_VARARGS, NULL}, {"setVersion", (PyCFunction)X509_object_set_version, METH_VARARGS, NULL}, {"getSerial", (PyCFunction)X509_object_get_serial, METH_VARARGS, NULL}, {"setSerial", (PyCFunction)X509_object_set_serial, METH_VARARGS, NULL}, {"getIssuer", (PyCFunction)X509_object_get_issuer, METH_VARARGS, NULL}, {"setIssuer", (PyCFunction)X509_object_set_issuer, METH_VARARGS, NULL}, {"getSubject", (PyCFunction)X509_object_get_subject, METH_VARARGS, NULL}, {"setSubject", (PyCFunction)X509_object_set_subject, METH_VARARGS, NULL}, {"getNotBefore", (PyCFunction)X509_object_get_not_before, METH_VARARGS, NULL}, {"getNotAfter", (PyCFunction)X509_object_get_not_after, METH_VARARGS, NULL}, {"setNotAfter", (PyCFunction)X509_object_set_not_after, METH_VARARGS, NULL}, {"setNotBefore", (PyCFunction)X509_object_set_not_before, METH_VARARGS, NULL}, {"addExtension", (PyCFunction)X509_object_add_extension, METH_VARARGS, NULL}, {"clearExtensions", (PyCFunction)X509_object_clear_extensions, METH_VARARGS, NULL}, {"countExtensions", (PyCFunction)X509_object_count_extensions, METH_VARARGS, NULL}, {"getExtension", (PyCFunction)X509_object_get_extension, METH_VARARGS, NULL}, {"pprint", (PyCFunction)x509_object_pprint, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * X509_object_getattr(x509_object *self, char *name) { return Py_FindMethod(X509_object_methods, (PyObject *)self, name); } static void X509_object_dealloc(x509_object *self, char *name) { X509_free(self->x509); PyObject_Del(self); } static char x509type__doc__[] = "\n" "
\n" " X509\n" "
\n" " \n" " \n" " This class provides access to a significant proportion of X509\n" " functionality of OpenSSL.\n" " \n" "\n" " \n" " <classname>x509</classname> class usage\n" " \n" " privateFile = open('test/private.key', 'r')\n" " publicFile = open('test/public.key', 'r')\n" " certFile = open('test/cacert.pem', 'w')\n" "\n" " publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n" " privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), 'pass')\n" "\n" " c = POW.X509()\n" "\n" " name = [ ['C', 'GB'], ['ST', 'Hertfordshire'],\n" " ['O','The House'], ['CN', 'Peter Shannon'] ]\n" "\n" " c.setIssuer(name)\n" " c.setSubject(name)\n" " c.setSerial(0)\n" " t1 = POW.pkix.time2utc(time.time())\n" " t2 = POW.pkix.time2utc(time.time() + 60*60*24*365)\n" " c.setNotBefore(t1)\n" " c.setNotAfter(t2)\n" " c.setPublicKey(publicKey)\n" " c.sign(privateKey)\n" "\n" " certFile.write(c.pemWrite())\n" "\n" " privateFile.close()\n" " publicFile.close()\n" " certFile.close()\n" " \n" " \n" "\n" " \n" "
\n" ; static PyTypeObject x509type = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "X509", /*tp_name*/ sizeof(x509_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)X509_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)X509_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, x509type__doc__ /* Documentation string */ }; /*========== X509 Code ==========*/ /*========== x509 store Code ==========*/ static x509_store_object * x509_store_object_new(void) { x509_store_object *self = NULL; if ((self = PyObject_New(x509_store_object, &x509_storetype)) == NULL) goto error; self->store = X509_STORE_new(); return self; error: Py_XDECREF(self); return NULL; } static char x509_store_object_verify__doc__[] = "\n" "
\n" " X509Store\n" " verify\n" " certificate\n" "
\n" " \n" " \n" " The X509Store method\n" " verify is based on the\n" " X509_verify_cert. It handles certain aspects\n" " of verification but not others. The certificate will be verified\n" " against notBefore,\n" " notAfter and trusted certificates.\n" " It crucially will not handle checking the certificate against\n" " CRLs. This functionality will probably make it into OpenSSL\n" " 0.9.7.\n" " \n" " \n" "
\n" ; static PyObject * x509_store_object_verify(x509_store_object *self, PyObject *args) { X509_STORE_CTX csc; x509_object *x509 = NULL; int ok; if (!PyArg_ParseTuple(args, "O!", &x509type, &x509)) goto error; X509_STORE_CTX_init(&csc, self->store, x509->x509, NULL); ok = X509_verify_cert(&csc) == 1; X509_STORE_CTX_cleanup(&csc); return PyBool_FromLong(ok); error: return NULL; } static char x509_store_object_verify_chain__doc__[] = "\n" "
\n" " X509Store\n" " verifyChain\n" " certificate\n" " chain\n" "
\n" " \n" " \n" " The X509Store method verifyChain\n" " is based on the X509_verify_cert but is initialised\n" " with a X509 object to verify and list of\n" " X509 objects which form a chain to a trusted\n" " certificate. Certain aspects of the verification are handled but not others.\n" " The certificates will be verified against notBefore,\n" " notAfter and trusted certificates. It crucially will\n" " not handle checking the certificate against CRLs. This functionality will\n" " probably make it into OpenSSL 0.9.7.\n" " \n" " \n" " This may all sound quite straight forward but determining the\n" " certificate associated with the signature on another certificate\n" " can be very time consuming. The management aspects of\n" " certificates are addressed by various V3 extensions which are not\n" " currently supported.\n" " \n" " \n" "
\n" ; static PyObject * x509_store_object_verify_chain(x509_store_object *self, PyObject *args) { PyObject *x509_sequence = NULL; X509_STORE_CTX csc; x509_object *x509 = NULL; STACK_OF(X509) *x509_stack = NULL; int ok; if (!PyArg_ParseTuple(args, "O!O", &x509type, &x509, &x509_sequence)) goto error; if ((x509_stack = x509_helper_sequence_to_stack(x509_sequence)) == NULL) goto error; X509_STORE_CTX_init(&csc, self->store, x509->x509, x509_stack); ok = X509_verify_cert(&csc) == 1; X509_STORE_CTX_cleanup(&csc); sk_X509_free(x509_stack); return PyBool_FromLong(ok); error: if (x509_stack) sk_X509_free(x509_stack); return NULL; } static char x509_store_object_verify_detailed__doc__[] = "\n" "
\n" " X509Store\n" " verifyDetailed\n" " certificate\n" " \n" " chain\n" " \n" "
\n" " \n" " \n" " The X509Store method verifyDetailed\n" " is based on the X509_verify_cert but is initialised\n" " with a X509 object to verify and list of\n" " X509 objects which form a chain to a trusted\n" " certificate. Certain aspects of the verification are handled but not others.\n" " The certificates will be verified against notBefore,\n" " notAfter and trusted certificates. It crucially will\n" " not handle checking the certificate against CRLs. This functionality will\n" " probably make it into OpenSSL 0.9.7.\n" " \n" " \n" " This may all sound quite straight forward but determining the\n" " certificate associated with the signature on another certificate\n" " can be very time consuming. The management aspects of\n" " certificates are addressed by various V3 extensions which are not\n" " currently supported.\n" " \n" " \n" " Unlike the verify and verifyChain\n" " methods, verifyDetailed returns some information about\n" " what went wrong when verification fails. The return value is currently a 3-tuple:\n" " the first value is the return value from X509_verify_cert(), the second and third\n" " are the error and error_depth values from the X509_STORE_CTX.\n" " Other values may added to this tuple later.\n" " \n" "
\n" ; static PyObject * x509_store_object_verify_detailed(x509_store_object *self, PyObject *args) { PyObject *x509_sequence = Py_None; X509_STORE_CTX csc; x509_object *x509 = NULL; STACK_OF(X509) *x509_stack = NULL; PyObject *result = NULL; int ok; if (!PyArg_ParseTuple(args, "O!|O", &x509type, &x509, &x509_sequence)) goto error; if (x509_sequence && !(x509_stack = x509_helper_sequence_to_stack(x509_sequence))) goto error; X509_STORE_CTX_init(&csc, self->store, x509->x509, x509_stack); ok = X509_verify_cert(&csc) == 1; result = Py_BuildValue("(iii)", ok, csc.error, csc.error_depth); X509_STORE_CTX_cleanup(&csc); error: /* fall through */ if (x509_stack) sk_X509_free(x509_stack); return result; } static char x509_store_object_add_trust__doc__[] = "\n" "
\n" " X509Store\n" " addTrust\n" " cert\n" "
\n" " \n" " \n" " This method adds a new certificate to the store to be used in the\n" " verification process. cert should be an\n" " instance of X509. Using trusted certificates to manage\n" " verification is relatively primitive, more sophisticated systems\n" " can be constructed at an application level by by constructing\n" " certificate chains to verify.\n" " \n" " \n" "
\n" ; static PyObject * x509_store_object_add_trust(x509_store_object *self, PyObject *args) { x509_object *x509 = NULL; if (!PyArg_ParseTuple(args, "O!", &x509type, &x509)) goto error; X509_STORE_add_cert(self->store, x509->x509); Py_RETURN_NONE; error: return NULL; } static char x509_store_object_add_crl__doc__[] = "\n" "
\n" " X509Store\n" " addCrl\n" " crl\n" "
\n" " \n" " \n" " This method adds a CRL to a store to be used for verification.\n" " crl should be an instance of\n" " X509Crl.\n" " Unfortunately, the current stable release of OpenSSL does not\n" " support CRL checking for certificate verification.\n" " This functionality will probably make it into OpenSSL 0.9.7, until\n" " it does this function is useless and CRL verification must be\n" " implemented by the application.\n" " \n" " \n" "
\n" ; static PyObject * x509_store_object_add_crl(x509_store_object *self, PyObject *args) { x509_crl_object *crl = NULL; if (!PyArg_ParseTuple(args, "O!", &x509_crltype, &crl)) goto error; X509_STORE_add_crl(self->store, crl->crl); Py_RETURN_NONE; error: return NULL; } static struct PyMethodDef x509_store_object_methods[] = { {"verify", (PyCFunction)x509_store_object_verify, METH_VARARGS, NULL}, {"verifyChain", (PyCFunction)x509_store_object_verify_chain, METH_VARARGS, NULL}, {"verifyDetailed", (PyCFunction)x509_store_object_verify_detailed, METH_VARARGS, NULL}, {"addTrust", (PyCFunction)x509_store_object_add_trust, METH_VARARGS, NULL}, {"addCrl", (PyCFunction)x509_store_object_add_crl, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * x509_store_object_getattr(x509_store_object *self, char *name) { return Py_FindMethod(x509_store_object_methods, (PyObject *)self, name); } static void x509_store_object_dealloc(x509_store_object *self, char *name) { X509_STORE_free(self->store); PyObject_Del(self); } static char x509_storetype__doc__[] = "\n" "
\n" " X509Store\n" "
\n" " \n" " \n" " This class provides preliminary access to OpenSSL X509 verification\n" " facilities.\n" " \n" "\n" " \n" " <classname>x509_store</classname> class usage\n" " \n" " store = POW.X509Store()\n" "\n" " caFile = open('test/cacert.pem', 'r')\n" " ca = POW.pemRead(POW.X509_CERTIFICATE, caFile.read())\n" " caFile.close()\n" "\n" " store.addTrust(ca)\n" "\n" " certFile = open('test/foocom.cert', 'r')\n" " x509 = POW.pemRead(POW.X509_CERTIFICATE, certFile.read())\n" " certFile.close()\n" "\n" " print x509.pprint()\n" "\n" " if store.verify(x509):\n" " print 'Verified certificate!.'\n" " else:\n" " print 'Failed to verify certificate!.'\n" " \n" " \n" " \n" "
\n" ; static PyTypeObject x509_storetype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "X509Store", /*tp_name*/ sizeof(x509_store_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)x509_store_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)x509_store_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, x509_storetype__doc__ /* Documentation string */ }; /*========== x509 store Code ==========*/ /*========== x509 crl Code ==========*/ static x509_crl_object * x509_crl_object_new(void) { x509_crl_object *self = NULL; self = PyObject_New(x509_crl_object, &x509_crltype); if (self == NULL) goto error; self->crl = X509_CRL_new(); return self; error: Py_XDECREF(self); return NULL; } static x509_crl_object * x509_crl_object_pem_read(BIO *in) { x509_crl_object *self; if ((self = PyObject_New(x509_crl_object, &x509_crltype)) == NULL) goto error; if ((self->crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL)) == NULL) lose("could not load certificate"); return self; error: Py_XDECREF(self); return NULL; } static x509_crl_object * x509_crl_object_der_read(unsigned char *src, int len) { x509_crl_object *self; unsigned char* ptr = src; if ((self = PyObject_New(x509_crl_object, &x509_crltype)) == NULL) goto error; self->crl = X509_CRL_new(); if (!d2i_X509_CRL(&self->crl, (const unsigned char **) &ptr, len)) lose("could not load PEM encoded CRL"); return self; error: Py_XDECREF(self); return NULL; } static char x509_crl_object_get_version__doc__[] = "\n" "
\n" " X509Crl\n" " getVersion\n" "
\n" " \n" " \n" " This method returns the version number from the version field of\n" " this CRL.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_get_version(x509_crl_object *self, PyObject *args) { long version = 0; if (!PyArg_ParseTuple(args, "")) goto error; if ((version = ASN1_INTEGER_get(self->crl->crl->version)) == -1) lose("could not get crl version"); return Py_BuildValue("l", version); error: return NULL; } static char x509_crl_object_set_version__doc__[] = "\n" "
\n" " X509Crl\n" " setVersion\n" " version\n" "
\n" " \n" " \n" " This method sets the version number in the version field of\n" " this CRL. version should be an\n" " integer.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_set_version(x509_crl_object *self, PyObject *args) { long version = 0; ASN1_INTEGER *asn1_version = NULL; if (!PyArg_ParseTuple(args, "i", &version)) goto error; if ((asn1_version = ASN1_INTEGER_new()) == NULL) lose("could not allocate memory"); if (!ASN1_INTEGER_set(asn1_version, version)) lose("could not get set version"); self->crl->crl->version = asn1_version; Py_RETURN_NONE; error: if (asn1_version) ASN1_INTEGER_free(asn1_version); return NULL; } static char x509_crl_object_get_issuer__doc__[] = "\n" "
\n" " X509Crl\n" " getIssuer\n" " format = SHORTNAME_FORMAT\n" "
\n" " \n" " \n" " This method returns a tuple containing the issuers name. See the\n" " getIssuer method of\n" " X509 for more details.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_get_issuer(x509_crl_object *self, PyObject *args) { PyObject *result_list = NULL; int format = SHORTNAME_FORMAT; if (!PyArg_ParseTuple(args, "|i", &format)) goto error; if ((result_list = X509_object_helper_get_name(self->crl->crl->issuer, format)) == NULL) lose("failed to produce name list"); return result_list; error: return NULL; } static char x509_crl_object_set_issuer__doc__[] = "\n" "
\n" " X509Crl\n" " setIssuer\n" " name\n" "
\n" " \n" " \n" " This method is used to set the issuers name.\n" " name can be comprised of lists or tuples in\n" " the format described in the getIssuer method\n" " of X509.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_set_issuer(x509_crl_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PyTuple_Check(name_sequence) && !PyList_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = X509_NAME_new()) == NULL) lose("could not allocate memory"); if (!X509_object_helper_set_name(name, name_sequence)) lose("unable to set new name"); if (!X509_NAME_set(&self->crl->crl->issuer, name)) lose("unable to set name"); X509_NAME_free(name); Py_RETURN_NONE; error: if (name) X509_NAME_free(name); return NULL; } static char x509_crl_object_set_this_update__doc__[] = "\n" "
\n" " X509Crl\n" " setThisUpdate\n" " time\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this accepts one parameter, a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_set_this_update (x509_crl_object *self, PyObject *args) { char *new_time = NULL; if (!PyArg_ParseTuple(args, "s", &new_time)) goto error; if (!python_ASN1_TIME_set_string(self->crl->crl->lastUpdate, new_time)) lose("Could not set lastUpdate"); Py_RETURN_NONE; error: return NULL; } static char x509_crl_object_get_this_update__doc__[] = "\n" "
\n" " X509Crl\n" " getThisUpdate\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this function returns a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_get_this_update (x509_crl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return ASN1_TIME_to_Python(self->crl->crl->lastUpdate); error: return NULL; } static char x509_crl_object_set_next_update__doc__[] = "\n" "
\n" " X509Crl\n" " setNextUpdate\n" " time\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this accepts one parameter, a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_set_next_update (x509_crl_object *self, PyObject *args) { char *new_time = NULL; ASN1_UTCTIME *time = NULL; if (!PyArg_ParseTuple(args, "s", &new_time)) goto error; if (self->crl->crl->nextUpdate == NULL && (time = ASN1_UTCTIME_new()) == NULL) lose("could not allocate memory"); self->crl->crl->nextUpdate = time; if (!python_ASN1_TIME_set_string(time, new_time)) lose("Could not set nextUpdate"); Py_RETURN_NONE; error: return NULL; } static char x509_crl_object_get_next_update__doc__[] = "\n" "
\n" " X509Crl\n" " getNextUpdate\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this function returns a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_get_next_update (x509_crl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return ASN1_TIME_to_Python(self->crl->crl->nextUpdate); error: return NULL; } static char x509_crl_object_set_revoked__doc__[] = "\n" "
\n" " X509Crl\n" " setRevoked\n" " revoked\n" "
\n" " \n" " \n" " This method sets the sequence of revoked certificates in this CRL.\n" " revoked should be a list or tuple of\n" " X509Revoked.\n" " \n" " \n" " <function>setRevoked</function> function usage\n" " \n" " privateFile = open('test/private.key', 'r')\n" " publicFile = open('test/public.key', 'r')\n" " crlFile = open('test/crl.pem', 'w')\n" "\n" " publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n" " privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), 'pass')\n" "\n" " crl = POW.X509Crl()\n" "\n" " name = [ ['C', 'GB'], ['ST', 'Hertfordshire'],\n" " ['O','The House'], ['CN', 'Peter Shannon'] ]\n" "\n" " t1 = POW.pkix.time2utc(time.time())\n" " t2 = POW.pkix.time2utc(time.time() + 60*60*24*365)\n" " crl.setIssuer(name)\n" " rev = [ POW.X509Revoked(3, t1),\n" " POW.X509Revoked(4, t1),\n" " POW.X509Revoked(5, t1) ]\n" "\n" " crl.setRevoked(rev)\n" " crl.setThisUpdate(t1)\n" " crl.setNextUpdate(t2)\n" " crl.sign(privateKey)\n" "\n" " crlFile.write(crl.pemWrite())\n" "\n" " privateFile.close()\n" " publicFile.close()\n" " crlFile.close()\n" " \n" " \n" "\n" " \n" "
\n" ; // added because we don't already have one! static X509_REVOKED * X509_REVOKED_dup(X509_REVOKED *rev) { return((X509_REVOKED *)ASN1_dup((i2d_of_void *) i2d_X509_REVOKED, (d2i_of_void *) d2i_X509_REVOKED, (char *) rev)); } static PyObject * x509_crl_object_set_revoked(x509_crl_object *self, PyObject *args) { PyObject *revoked_sequence = NULL; x509_revoked_object *revoked = NULL; X509_REVOKED *tmp_revoked = NULL; int i = 0,size = 0; if (!PyArg_ParseTuple(args, "O", &revoked_sequence)) goto error; if (!PyTuple_Check(revoked_sequence) && !PyList_Check(revoked_sequence)) lose_type_error("inapropriate type"); size = PySequence_Size(revoked_sequence); for (i = 0; i < size; i++) { if ((revoked = (x509_revoked_object*) PySequence_GetItem(revoked_sequence, i)) == NULL) goto error; if (!X_X509_revoked_Check(revoked)) lose_type_error("inapropriate type"); if ((tmp_revoked = X509_REVOKED_dup(revoked->revoked)) == NULL) lose("could not allocate memory"); if (!X509_CRL_add0_revoked(self->crl, tmp_revoked)) lose("could not add revokation to stack"); Py_XDECREF(revoked); revoked = NULL; } Py_RETURN_NONE; error: Py_XDECREF(revoked); return NULL; } static PyObject * x509_crl_object_helper_get_revoked(STACK_OF(X509_REVOKED) *revoked) { int no_entries = 0, i = 0; x509_revoked_object *revoke_obj = NULL; PyObject *result_list = NULL, *result_tuple = NULL; no_entries = sk_X509_REVOKED_num(revoked); if ((result_list = PyList_New(0)) == NULL) lose("could not allocate memory"); for (i = 0; i < no_entries; i++) { if ((revoke_obj = PyObject_New(x509_revoked_object, &x509_revokedtype)) == NULL) lose("could not allocate memory"); if ((revoke_obj->revoked = X509_REVOKED_dup(sk_X509_REVOKED_value(revoked, i))) == NULL) lose("could not get revocation"); if (PyList_Append(result_list, (PyObject*) revoke_obj) != 0) goto error; Py_XDECREF(revoke_obj); revoke_obj = NULL; } result_tuple = PyList_AsTuple(result_list); Py_XDECREF(result_list); return result_tuple; error: Py_XDECREF(revoke_obj); Py_XDECREF(result_list); return NULL; } static char x509_crl_object_get_revoked__doc__[] = "\n" "
\n" " X509Crl\n" " getRevoked\n" "
\n" " \n" " \n" " This method returns a tuple of X509Revoked\n" " objects described in the CRL.\n" " \n" " \n" " <function>getRevoked</function> function usage\n" " \n" " publicFile = open('test/public.key', 'r')\n" " crlFile = open('test/crl.pem', 'r')\n" "\n" " publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n" "\n" " crl = POW.pemRead(POW.X509_CRL, crlFile.read())\n" "\n" " print crl.pprint()\n" " if crl.verify(publicKey):\n" " print 'signature ok!'\n" " else:\n" " print 'signature not ok!'\n" "\n" " revocations = crl.getRevoked()\n" " for revoked in revocations:\n" " print 'serial number:', revoked.getSerial()\n" " print 'date:', time.ctime(revoked.getDate()[0])\n" "\n" " publicFile.close()\n" " crlFile.close()\n" " \n" " \n" "\n" " \n" "
\n" ; static PyObject * x509_crl_object_get_revoked(x509_crl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return x509_crl_object_helper_get_revoked(X509_CRL_get_REVOKED(self->crl)); error: return NULL; } static char X509_crl_object_add_extension__doc__[] = "\n" "
\n" " X509Crl\n" " addExtension\n" " extensionName\n" " critical\n" " extensionValue\n" "
\n" " \n" " \n" " This method adds an extension to this CRL.\n" " extensionName should be the of the\n" " extension. critical should an integer, 1\n" " for true and 0 for clase. extensionValue\n" " should be a string, DER encoded value of the extension. The name\n" " of the extension must be correct according to OpenSSL and can be\n" " checkd in the objects.h header file, part of\n" " the OpenSSL source distrobution. In the majority of cases they\n" " are the same as those defined in POW._oids\n" " but if you do encounter problems is may be worth checking.\n" " \n" " \n" " <function>addExtension</function> method usage\n" " \n" " oids = POW.pkix.OidData()\n" " o2i = oids.obj2oid\n" "\n" " n1 = ('directoryName', (((o2i('countryName'), ('printableString', 'UK')),),\n" " ((o2i('stateOrProvinceName'), ('printableString', 'Herts')),),\n" " ((o2i('organizationName'), ('printableString', 'The House')),),\n" " ((o2i('commonName'), ('printableString', 'Shannon Works')),)))\n" "\n" " n2 = ('rfc822Name', 'peter_shannon@yahoo.com')\n" " n3 = ('uri', 'http://www.p-s.org.uk')\n" " n4 = ('iPAddress', (192,168,100,51))\n" "\n" " issuer = POW.pkix.IssuerAltName()\n" " issuer.set([n1,n2,n3,n4])\n" " crl.addExtension('issuerAltName', 0, issuer.toString())\n" " \n" " \n" " \n" "
\n" ; static PyObject * X509_crl_object_add_extension(x509_crl_object *self, PyObject *args) { int critical = 0, nid = 0, len = 0; char *name = NULL; unsigned char *buf = NULL; ASN1_OCTET_STRING *octetString = NULL; X509_EXTENSION *extn = NULL; if (!PyArg_ParseTuple(args, "sis#", &name, &critical, &buf, &len)) goto error; if ((octetString = M_ASN1_OCTET_STRING_new()) == NULL) lose("could not allocate memory"); if (!ASN1_OCTET_STRING_set(octetString, buf, len)) lose("could not set ASN1 Octect string"); if ((nid = OBJ_txt2nid(name)) == NID_undef) lose("extension has unknown object identifier"); if ((extn = X509_EXTENSION_create_by_NID(NULL, nid, critical, octetString)) == NULL) lose("unable to create ASN1 X509 Extension object"); if (!self->crl->crl->extensions && (self->crl->crl->extensions = sk_X509_EXTENSION_new_null()) == NULL) lose("unable to allocate memory"); if (!sk_X509_EXTENSION_push(self->crl->crl->extensions, extn)) lose("unable to add extension"); Py_RETURN_NONE; error: if (extn) X509_EXTENSION_free(extn); return NULL; } static char X509_crl_object_clear_extensions__doc__[] = "\n" "
\n" " X509Crl\n" " clearExtensions\n" "
\n" " \n" " \n" " This method clears the structure which holds the extension for\n" " this CRL.\n" " \n" " \n" "
\n" ; static PyObject * X509_crl_object_clear_extensions(x509_crl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; if (self->crl->crl->extensions) { sk_X509_EXTENSION_free(self->crl->crl->extensions); self->crl->crl->extensions = NULL; } Py_RETURN_NONE; error: return NULL; } static char X509_crl_object_count_extensions__doc__[] = "\n" "
\n" " X509Crl\n" " countExtensions\n" "
\n" " \n" " \n" " This method returns the size of the structure which holds the\n" " extension for this CRL.\n" " \n" " \n" "
\n" ; static PyObject * X509_crl_object_count_extensions(x509_crl_object *self, PyObject *args) { int num = 0; if (!PyArg_ParseTuple(args, "")) goto error; if (self->crl->crl->extensions) num = sk_X509_EXTENSION_num(self->crl->crl->extensions); return Py_BuildValue("i", num); error: return NULL; } static char X509_crl_object_get_extension__doc__[] = "\n" "
\n" " X509Crl\n" " getExtension\n" " index\n" "
\n" " \n" " \n" " This method returns a tuple equivalent the parameters of\n" " addExtension.\n" " \n" " \n" "
\n" ; static PyObject * X509_crl_object_get_extension(x509_crl_object *self, PyObject *args) { int num = 0, index = 0, ext_nid = 0; char const *ext_ln = NULL; char unknown_ext [] = "unknown"; X509_EXTENSION *ext; if (!PyArg_ParseTuple(args, "i", &index)) goto error; if (self->crl->crl->extensions) num = sk_X509_EXTENSION_num(self->crl->crl->extensions); if (index >= num) lose("certificate does not have that many extensions"); if ((ext = sk_X509_EXTENSION_value(self->crl->crl->extensions, index)) == NULL) lose("could not get extension"); if ((ext_nid = OBJ_obj2nid(ext->object)) == NID_undef) lose("extension has unknown object identifier"); if ((ext_ln = OBJ_nid2sn(ext_nid)) == NULL) ext_ln = unknown_ext; return Py_BuildValue("sis#", ext_ln, ext->critical, ext->value->data, ext->value->length); error: return NULL; } static char x509_crl_object_sign__doc__[] = "\n" "
\n" " X509Crl\n" " sign\n" " key\n" " digest = MD5_DIGEST\n" "
\n" " \n" " \n" " key should be an instance of\n" " Asymmetric and contain a private key.\n" " digest indicates\n" " which digest function should be used to compute the hash to be\n" " signed, it should be one of the following:\n" " \n" " \n" #ifndef OPENSSL_NO_MD2 " MD2_DIGEST\n" #endif " MD5_DIGEST\n" " SHA_DIGEST\n" " SHA1_DIGEST\n" " RIPEMD160_DIGEST\n" " SHA256_DIGEST\n" " SHA384_DIGEST\n" " SHA512_DIGEST\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_sign(x509_crl_object *self, PyObject *args) { EVP_PKEY *pkey = NULL; asymmetric_object *asym; int digest = MD5_DIGEST; if (!PyArg_ParseTuple(args, "O!|i", &asymmetrictype, &asym, &digest)) goto error; if ((pkey = EVP_PKEY_new()) == NULL) lose("could not allocate memory"); if (asym->key_type != RSA_PRIVATE_KEY) lose("cannot use this type of key"); if (!EVP_PKEY_assign_RSA(pkey, asym->cipher)) lose("EVP_PKEY assignment error"); switch (digest) { case MD5_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_md5())) lose("could not sign CRL"); break; #ifndef OPENSSL_NO_MD2 case MD2_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_md2())) lose("could not sign CRL"); break; #endif case SHA_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_sha())) lose("could not sign CRL"); break; case SHA1_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_sha1())) lose("could not sign CRL"); break; case RIPEMD160_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_ripemd160())) lose("could not sign CRL"); break; case SHA256_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_sha256())) lose("could not sign CRL"); break; case SHA384_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_sha384())) lose("could not sign CRL"); break; case SHA512_DIGEST: if (!X509_CRL_sign(self->crl, pkey, EVP_sha512())) lose("could not sign CRL"); break; } Py_RETURN_NONE; error: if (pkey) EVP_PKEY_free(pkey); return NULL; } static char x509_crl_object_verify__doc__[] = "\n" "
\n" " X509Crl\n" " verify\n" " key\n" "
\n" " \n" " \n" " The X509Crl method\n" " verify is based on the\n" " X509_CRL_verify function. Unlike the\n" " X509 function of the same name, this\n" " function simply checks the CRL was signed with the private key\n" " which corresponds the parameter key.\n" " key should be an instance of\n" " Asymmetric and contain a public key.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_verify(x509_crl_object *self, PyObject *args) { EVP_PKEY *pkey = NULL; asymmetric_object *asym; int ok; if (!PyArg_ParseTuple(args, "O!", &asymmetrictype, &asym)) goto error; if ((pkey = EVP_PKEY_new()) == NULL) lose("could not allocate memory"); if (!EVP_PKEY_assign_RSA(pkey, asym->cipher)) lose("EVP_PKEY assignment error"); ok = X509_CRL_verify(self->crl, pkey); return PyBool_FromLong(ok); error: if (pkey) EVP_PKEY_free(pkey); return NULL; } static PyObject * x509_crl_object_write_helper(x509_crl_object *self, PyObject *args, int format) { int len = 0, ret = 0; char *buf = NULL; BIO *out_bio = NULL; PyObject *cert = NULL; if (!PyArg_ParseTuple(args, "")) goto error; out_bio = BIO_new(BIO_s_mem()); switch (format) { case DER_FORMAT: if (!i2d_X509_CRL_bio(out_bio, self->crl)) lose("unable to write certificate"); break; case PEM_FORMAT: if (!PEM_write_bio_X509_CRL(out_bio, self->crl)) lose("unable to write certificate"); default: lose("internal error, unknown output format"); } if ((len = BIO_ctrl_pending(out_bio)) == 0) lose("unable to get bytes stored in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if ((ret = BIO_read(out_bio, buf, len)) != len) lose("unable to write out cert"); cert = Py_BuildValue("s#", buf, len); BIO_free(out_bio); free(buf); return cert; error: if (out_bio) BIO_free(out_bio); if (buf) free(buf); return NULL; } static char x509_crl_object_pem_write__doc__[] = "\n" "
\n" " X509Crl\n" " pemWrite\n" "
\n" " \n" " \n" " This method returns a PEM encoded CRL as a\n" " string.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_pem_write(x509_crl_object *self, PyObject *args) { return x509_crl_object_write_helper(self, args, PEM_FORMAT); } static char x509_crl_object_der_write__doc__[] = "\n" "
\n" " X509Crl\n" " derWrite\n" "
\n" " \n" " \n" " This method returns a DER encoded CRL as a string.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_der_write(x509_crl_object *self, PyObject *args) { return x509_crl_object_write_helper(self, args, DER_FORMAT); } static char x509_crl_object_pprint__doc__[] = "\n" "
\n" " X509Crl\n" " pprint\n" "
\n" " \n" " \n" " This method returns a formatted string showing the information\n" " held in the CRL.\n" " \n" " \n" "
\n" ; static PyObject * x509_crl_object_pprint(x509_crl_object *self, PyObject *args) { int len = 0, ret = 0; char *buf = NULL; BIO *out_bio = NULL; PyObject *crl = NULL; if (!PyArg_ParseTuple(args, "")) goto error; out_bio = BIO_new(BIO_s_mem()); if (!X509_CRL_print(out_bio, self->crl)) lose("unable to write crl"); if ((len = BIO_ctrl_pending(out_bio)) == 0) lose("unable to get bytes stored in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if ((ret = BIO_read(out_bio, buf, len)) != len) lose("unable to write out cert"); crl = Py_BuildValue("s#", buf, len); BIO_free(out_bio); free(buf); return crl; error: if (out_bio) BIO_free(out_bio); if (buf) free(buf); return NULL; } static struct PyMethodDef x509_crl_object_methods[] = { {"sign", (PyCFunction)x509_crl_object_sign, METH_VARARGS, NULL}, {"verify", (PyCFunction)x509_crl_object_verify, METH_VARARGS, NULL}, {"getVersion", (PyCFunction)x509_crl_object_get_version, METH_VARARGS, NULL}, {"setVersion", (PyCFunction)x509_crl_object_set_version, METH_VARARGS, NULL}, {"getIssuer", (PyCFunction)x509_crl_object_get_issuer, METH_VARARGS, NULL}, {"setIssuer", (PyCFunction)x509_crl_object_set_issuer, METH_VARARGS, NULL}, {"getThisUpdate", (PyCFunction)x509_crl_object_get_this_update, METH_VARARGS, NULL}, {"setThisUpdate", (PyCFunction)x509_crl_object_set_this_update, METH_VARARGS, NULL}, {"getNextUpdate", (PyCFunction)x509_crl_object_get_next_update, METH_VARARGS, NULL}, {"setNextUpdate", (PyCFunction)x509_crl_object_set_next_update, METH_VARARGS, NULL}, {"setRevoked", (PyCFunction)x509_crl_object_set_revoked, METH_VARARGS, NULL}, {"getRevoked", (PyCFunction)x509_crl_object_get_revoked, METH_VARARGS, NULL}, {"addExtension", (PyCFunction)X509_crl_object_add_extension, METH_VARARGS, NULL}, {"clearExtensions", (PyCFunction)X509_crl_object_clear_extensions, METH_VARARGS, NULL}, {"countExtensions", (PyCFunction)X509_crl_object_count_extensions, METH_VARARGS, NULL}, {"getExtension", (PyCFunction)X509_crl_object_get_extension, METH_VARARGS, NULL}, {"pemWrite", (PyCFunction)x509_crl_object_pem_write, METH_VARARGS, NULL}, {"derWrite", (PyCFunction)x509_crl_object_der_write, METH_VARARGS, NULL}, {"pprint", (PyCFunction)x509_crl_object_pprint, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * x509_crl_object_getattr(x509_crl_object *self, char *name) { return Py_FindMethod(x509_crl_object_methods, (PyObject *)self, name); } static void x509_crl_object_dealloc(x509_crl_object *self, char *name) { X509_CRL_free(self->crl); PyObject_Del(self); } static char x509_crltype__doc__[] = "\n" "
\n" " X509Crl\n" "
\n" " \n" " \n" " This class provides access to OpenSSL X509 CRL management\n" " facilities.\n" " \n" " \n" "
\n" ; static PyTypeObject x509_crltype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "X509Crl", /*tp_name*/ sizeof(x509_crl_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)x509_crl_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)x509_crl_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, x509_crltype__doc__ /* Documentation string */ }; /*========== x509 crl Code ==========*/ /*========== revoked Code ==========*/ x509_revoked_object* x509_revoked_object_new(void) { x509_revoked_object *self = NULL; if ((self = PyObject_New(x509_revoked_object, &x509_revokedtype)) == NULL) goto error; self->revoked = X509_REVOKED_new(); return self; error: Py_XDECREF(self); return NULL; } static char x509_revoked_object_set_serial__doc__[] = "\n" "
\n" " X509Revoked\n" " setSerial\n" " serial\n" "
\n" " \n" " \n" " This method sets the serial number in the serial field of\n" " this object. serial should be an\n" " integer.\n" " \n" " \n" "
\n" ; static PyObject * x509_revoked_object_set_serial(x509_revoked_object *self, PyObject *args) { int serial = 0; if (!PyArg_ParseTuple(args, "i", &serial)) goto error; if (!ASN1_INTEGER_set(self->revoked->serialNumber, serial)) lose("unable to set serial number"); Py_RETURN_NONE; error: return NULL; } static char x509_revoked_object_get_serial__doc__[] = "\n" "
\n" " X509Revoked\n" " getSerial\n" "
\n" " \n" " \n" " This method gets the serial number in the serial field of\n" " this object.\n" " \n" " \n" "
\n" ; static PyObject * x509_revoked_object_get_serial(x509_revoked_object *self, PyObject *args) { int serial = 0; if (!PyArg_ParseTuple(args, "")) goto error; if ((serial = ASN1_INTEGER_get(self->revoked->serialNumber)) == -1) lose("unable to get serial number"); return Py_BuildValue("i", serial); error: return NULL; } static char x509_revoked_object_get_date__doc__[] = "\n" "
\n" " X509Revoked\n" " getDate\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this function returns a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * x509_revoked_object_get_date(x509_revoked_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return ASN1_TIME_to_Python(self->revoked->revocationDate); error: return NULL; } static char x509_revoked_object_set_date__doc__[] = "\n" "
\n" " X509Revoked\n" " setDate\n" " time\n" "
\n" " \n" " \n" " In a change from previous releases, for reasons of portability\n" " and to avoid hard to fix issues with problems in unreliable time\n" " functions, this accepts one parameter, a UTCTime string. You\n" " can use the function time2utc to convert to a\n" " string if you like and utc2time to back.\n" " \n" " \n" "
\n" ; static PyObject * x509_revoked_object_set_date(x509_revoked_object *self, PyObject *args) { char *time = NULL; if (!PyArg_ParseTuple(args, "s", &time)) goto error; if (!python_ASN1_TIME_set_string(self->revoked->revocationDate, time)) lose_type_error("Could not set revocationDate"); Py_RETURN_NONE; error: return NULL; } static char X509_revoked_object_add_extension__doc__[] = "\n" "
\n" " X509Revoked\n" " addExtension\n" " extensionName\n" " critical\n" " extensionValue\n" "
\n" " \n" " \n" " This method adds an extension to this revocation.\n" " extensionName should be the of the\n" " extension. critical should an integer, 1\n" " for true and 0 for clase. extensionValue\n" " should be a string, DER encoded value of the extension. The name\n" " of the extension must be correct according to OpenSSL and can be\n" " checkd in the objects.h header file, part of\n" " the OpenSSL source distrobution. In the majority of cases they\n" " are the same as those defined in POW._oids\n" " but if you do encounter problems is may be worth checking.\n" " \n" " \n" " <function>addExtension</function> method usage\n" " \n" " reason = POW.pkix.CrlReason()\n" " reason.set(1)\n" " revocation.addExtension('CRLReason', 0, reason.toString())\n" " \n" " \n" " \n" "
\n" ; static PyObject * X509_revoked_object_add_extension(x509_revoked_object *self, PyObject *args) { int critical = 0, nid = 0, len = 0; char *name = NULL; unsigned char *buf = NULL; ASN1_OCTET_STRING *octetString = NULL; X509_EXTENSION *extn = NULL; if (!PyArg_ParseTuple(args, "sis#", &name, &critical, &buf, &len)) goto error; if ((octetString = M_ASN1_OCTET_STRING_new()) == NULL) lose("could not allocate memory"); if (!ASN1_OCTET_STRING_set(octetString, buf, strlen((char *) buf))) lose("could not set ASN1 Octect string"); if ((nid = OBJ_txt2nid(name)) == NID_undef) lose("extension has unknown object identifier"); if ((extn = X509_EXTENSION_create_by_NID(NULL, nid, critical, octetString)) == NULL) lose("unable to create ASN1 X509 Extension object"); if (!self->revoked->extensions && (self->revoked->extensions = sk_X509_EXTENSION_new_null()) == NULL) lose("unable to allocate memory"); if (!sk_X509_EXTENSION_push(self->revoked->extensions, extn)) lose("unable to add extension"); Py_RETURN_NONE; error: if (extn) X509_EXTENSION_free(extn); return NULL; } static char X509_revoked_object_clear_extensions__doc__[] = "\n" "
\n" " X509Revoked\n" " clearExtensions\n" "
\n" " \n" " \n" " This method clears the structure which holds the extension for\n" " this revocation.\n" " \n" " \n" "
\n" ; static PyObject * X509_revoked_object_clear_extensions(x509_revoked_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; if (self->revoked->extensions) { sk_X509_EXTENSION_free(self->revoked->extensions); self->revoked->extensions = NULL; } Py_RETURN_NONE; error: return NULL; } static char X509_revoked_object_count_extensions__doc__[] = "\n" "
\n" " X509Revoked\n" " countExtensions\n" "
\n" " \n" " \n" " This method returns the size of the structure which holds the\n" " extension for this revocation.\n" " \n" " \n" "
\n" ; static PyObject * X509_revoked_object_count_extensions(x509_revoked_object *self, PyObject *args) { int num = 0; if (!PyArg_ParseTuple(args, "")) goto error; if (self->revoked->extensions) num = sk_X509_EXTENSION_num(self->revoked->extensions); return Py_BuildValue("i", num); error: return NULL; } static char X509_revoked_object_get_extension__doc__[] = "\n" "
\n" " X509Revoked\n" " getExtension\n" " index\n" "
\n" " \n" " \n" " This method returns a tuple equivalent the parameters of\n" " addExtension.\n" " \n" " \n" "
\n" ; static PyObject * X509_revoked_object_get_extension(x509_revoked_object *self, PyObject *args) { int num = 0, index = 0, ext_nid = 0; char const *ext_ln = NULL; char unknown_ext [] = "unknown"; X509_EXTENSION *ext; if (!PyArg_ParseTuple(args, "i", &index)) goto error; if (self->revoked->extensions) num = sk_X509_EXTENSION_num(self->revoked->extensions); if (index >= num) lose("certificate does not have that many extensions"); if ((ext = sk_X509_EXTENSION_value(self->revoked->extensions, index)) == NULL) lose("could not get extension"); if ((ext_nid = OBJ_obj2nid(ext->object)) == NID_undef) lose("extension has unknown object identifier"); if ((ext_ln = OBJ_nid2sn(ext_nid)) == NULL) ext_ln = unknown_ext; return Py_BuildValue("sis#", ext_ln, ext->critical, ext->value->data, ext->value->length); error: return NULL; } static struct PyMethodDef x509_revoked_object_methods[] = { {"getSerial", (PyCFunction)x509_revoked_object_get_serial, METH_VARARGS, NULL}, {"setSerial", (PyCFunction)x509_revoked_object_set_serial, METH_VARARGS, NULL}, {"getDate", (PyCFunction)x509_revoked_object_get_date, METH_VARARGS, NULL}, {"setDate", (PyCFunction)x509_revoked_object_set_date, METH_VARARGS, NULL}, {"addExtension", (PyCFunction)X509_revoked_object_add_extension, METH_VARARGS, NULL}, {"clearExtensions", (PyCFunction)X509_revoked_object_clear_extensions, METH_VARARGS, NULL}, {"countExtensions", (PyCFunction)X509_revoked_object_count_extensions, METH_VARARGS, NULL}, {"getExtension", (PyCFunction)X509_revoked_object_get_extension, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * x509_revoked_object_getattr(x509_revoked_object *self, char *name) { return Py_FindMethod(x509_revoked_object_methods, (PyObject *) self, name); } static void x509_revoked_object_dealloc(x509_revoked_object *self, char *name) { X509_REVOKED_free(self->revoked); PyObject_Del(self); } static char x509_revokedtype__doc__[] = "\n" "
\n" " X509Revoked\n" "
\n" " \n" " \n" " This class provides a container for details of a revoked\n" " certificate. It normally would only be used in association with\n" " a CRL, its not much use by itself. Indeed the only reason this\n" " class exists is because in the future POW is likely to be extended\n" " to support extensions for certificates, CRLs and revocations.\n" " X509Revoked existing as an object in its\n" " own right will make adding this support easier, while avoiding\n" " backwards compatibility issues.\n" " \n" " \n" "
\n" ; static PyTypeObject x509_revokedtype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "X509Revoked", /*tp_name*/ sizeof(x509_revoked_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)x509_revoked_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)x509_revoked_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, x509_revokedtype__doc__ /* Documentation string */ }; /*========== x509 revoked Code ==========*/ /*========== ssl Code ==========*/ static char ssl_object_use_certificate__doc__[] = "\n" "
\n" " Ssl\n" " useCertificate\n" " cert\n" "
\n" " \n" " \n" " The parameter cert must be an\n" " instance of the X590 class and must be\n" " called before setFd.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_use_certificate(ssl_object *self, PyObject *args) { x509_object *x509 = NULL; if (!PyArg_ParseTuple(args, "O!", &x509type, &x509)) goto error; if (self->ctxset) lose("cannot be called after setFd()"); if (!SSL_CTX_use_certificate(self->ctx, x509->x509)) lose("could not use certificate"); Py_RETURN_NONE; error: return NULL; } static PyObject * ssl_object_add_certificate(ssl_object *self, PyObject *args) { x509_object *x509 = NULL; X509 *x = NULL; if (!PyArg_ParseTuple(args, "O!", &x509type, &x509)) goto error; if (self->ctxset) lose("cannot be called after setFd()"); if ((x = X509_dup(x509->x509)) == NULL) lose("could not duplicate X509 object"); if (!SSL_CTX_add_extra_chain_cert(self->ctx, x)) lose_openssl_error("Could not add certificate"); x = NULL; Py_RETURN_NONE; error: if (x) X509_free(x); return NULL; } static PyObject * ssl_object_add_trust(ssl_object *self, PyObject *args) { x509_object *x509 = NULL; X509 *x = NULL; if (!PyArg_ParseTuple(args, "O!", &x509type, &x509)) goto error; if (self->ctxset) lose("Cannot be called after setFd()"); if (self->trusted_certs == NULL && (self->trusted_certs = sk_X509_new_null()) == NULL) lose("Couldn't allocate trusted certificate stack"); if ((x = X509_dup(x509->x509)) == NULL) lose("Couldn't duplicate X509 object"); if (!sk_X509_push(self->trusted_certs, x)) lose("Couldn't push cert onto trusted certificate stack"); x = NULL; Py_RETURN_NONE; error: if (x) X509_free(x); return NULL; } static char ssl_object_use_key__doc__[] = "\n" "
\n" " Ssl\n" " useKey\n" " key\n" "
\n" " \n" " \n" " The parameter key must be an\n" " instance of the Asymmetric class and\n" " must contain the private key. This function cannot be called\n" " after useKey.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_use_key(ssl_object *self, PyObject *args) { asymmetric_object *asym = NULL; EVP_PKEY *pkey = NULL; if (!PyArg_ParseTuple(args, "O!", &asymmetrictype, &asym)) goto error; if (self->ctxset) lose("cannot be called after setFd()"); if ((pkey = EVP_PKEY_new()) == NULL) lose("could not allocate memory"); if (asym->key_type != RSA_PRIVATE_KEY) lose("cannot use this type of key"); if (!EVP_PKEY_set1_RSA(pkey, asym->cipher)) lose("EVP_PKEY assignment error"); if (!SSL_CTX_use_PrivateKey(self->ctx, pkey)) lose("ctx key assignment error"); Py_RETURN_NONE; error: if(pkey) EVP_PKEY_free(pkey); return NULL; } static char ssl_object_check_key__doc__[] = "\n" "
\n" " Ssl\n" " checkKey\n" "
\n" " \n" " \n" " This simple method will return 1 if the public key, contained in\n" " the X509 certificate this Ssl instance is using,\n" " matches the private key this Ssl instance is using.\n" " Otherwise it will return 0.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_check_key(ssl_object *self, PyObject *args) { return PyBool_FromLong(SSL_CTX_check_private_key(self->ctx)); } static char ssl_object_set_fd__doc__[] = "\n" "
\n" " Ssl\n" " setFd\n" " descriptor\n" "
\n" " \n" " \n" " This function is used to associate a file descriptor with a\n" " Ssl object. The file descriptor should\n" " belong to an open TCP connection. Once this function has\n" " been called, calling useKey or\n" " useCertificate will, fail rasing exceptions.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_set_fd(ssl_object *self, PyObject *args) { int fd = 0, self_index = 0; if (!PyArg_ParseTuple(args, "i", &fd)) goto error; if ((self->ssl = SSL_new(self->ctx)) == NULL) lose("Unable to create ssl structure"); SSL_set_mode(self->ssl, (SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)); if (!SSL_set_fd(self->ssl, fd)) lose("Unable to set file descriptor"); if ((self_index = SSL_get_ex_new_index(0, "self_index", NULL, NULL, NULL)) != -1) SSL_set_ex_data(self->ssl, self_index, self); else lose("Unable to create ex data index"); self->ctxset = 1; Py_RETURN_NONE; error: return NULL; } static char ssl_object_fileno__doc__[] = "\n" "
\n" " Ssl\n" " fileno\n" "
\n" " \n" " \n" " This function is used to extract the file descriptor associated\n" " with a Ssl object.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_fileno(ssl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); return Py_BuildValue("i", SSL_get_fd(self->ssl)); error: return NULL; } static char ssl_object_accept__doc__[] = "\n" "
\n" " Ssl\n" " accept\n" "
\n" " \n" " \n" " This function will attempt the SSL level accept with a\n" " client. The Ssl object must have been\n" " created using a XXXXX_SERVER_METHOD or\n" " a XXXXX_METHOD and this function should only be\n" " called after useKey,\n" " useCertificate and\n" " setFd functions have been called.\n" " \n" "\n" " \n" " <function>accept</function> function usage\n" " \n" " keyFile = open('test/private.key', 'r')\n" " certFile = open('test/cacert.pem', 'r')\n" "\n" " rsa = POW.pemRead(POW.RSA_PRIVATE_KEY, keyFile.read(), 'pass')\n" " x509 = POW.pemRead(POW.X509_CERTIFICATE, certFile.read())\n" "\n" " keyFile.close()\n" " certFile.close()\n" "\n" " sl = POW.Ssl(POW.SSLV23_SERVER_METHOD)\n" " sl.useCertificate(x509)\n" " sl.useKey(rsa)\n" "\n" " s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n" " s.bind(('localhost', 1111))\n" " s.listen(5)\n" " s2, addr = s.accept()\n" "\n" " s.close()\n" "\n" " sl.setFd(s2.fileno())\n" " sl.accept()\n" " print sl.read(1024)\n" " sl.write('Message from server to client...')\n" "\n" " s2.close()\n" " \n" " \n" " \n" "
\n" ; static PyObject * ssl_object_accept(ssl_object *self, PyObject *args) { int ret = 0; if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); Py_BEGIN_ALLOW_THREADS; ret = SSL_accept(self->ssl); Py_END_ALLOW_THREADS; if (ret <= 0) lose_ssl_error(self, ret); Py_RETURN_NONE; error: return NULL; } static char ssl_object_connect__doc__[] = "\n" "
\n" " Ssl\n" " connect\n" "
\n" " \n" " \n" " This function will attempt the SSL level connection with a\n" " server. The Ssl object must have been\n" " created using a XXXXX_CLIENT_METHOD or\n" " a XXXXX_METHOD and this function should only be\n" " called after setFd has already been\n" " called.\n" " \n" "\n" " \n" " <function>connect</function> function usage\n" " \n" " s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n" " s.connect(('localhost', 1111))\n" "\n" " sl = POW.Ssl(POW.SSLV23_CLIENT_METHOD)\n" " sl.setFd(s.fileno())\n" " sl.connect()\n" " sl.write('Message from client to server...')\n" " print sl.read(1024)\n" " \n" " \n" " \n" "
\n" ; static PyObject * ssl_object_connect(ssl_object *self, PyObject *args) { int ret; if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); Py_BEGIN_ALLOW_THREADS; ret = SSL_connect(self->ssl); Py_END_ALLOW_THREADS; if (ret <= 0) lose_ssl_error(self, ret); Py_RETURN_NONE; error: return NULL; } static char ssl_object_write__doc__[] = "\n" "
\n" " Ssl\n" " write\n" " string\n" "
\n" " \n" " \n" " This method writes the string to the\n" " Ssl object, to be read by it's peer. This\n" " function is analogous to the socket\n" " classes write function.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_write(ssl_object *self, PyObject *args) { char *msg; int length = 0, ret = 0; if (!PyArg_ParseTuple(args, "s#", &msg, &length)) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); Py_BEGIN_ALLOW_THREADS; ret = SSL_write(self->ssl, msg, length); Py_END_ALLOW_THREADS; if (ret <= 0) lose_ssl_error(self, ret); return Py_BuildValue("i", ret); error: return NULL; } static char ssl_object_read__doc__[] = "\n" "
\n" " Ssl\n" " read\n" " amount = 1024\n" "
\n" " \n" " \n" " This method reads up to amount characters from the\n" " Ssl object. This\n" " function is analogous to the socket\n" " classes read function.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_read(ssl_object *self, PyObject *args) { PyObject *data; char *msg = NULL; int len = 1024, ret = 0; if (!PyArg_ParseTuple(args, "|i", &len)) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); if ((msg = malloc(len)) == NULL) lose("unable to allocate memory"); Py_BEGIN_ALLOW_THREADS; ret = SSL_read(self->ssl, msg, len); Py_END_ALLOW_THREADS; if (ret <= 0) lose_ssl_error(self, ret); data = Py_BuildValue("s#", msg, ret); free(msg); return data; error: if (msg) free(msg); return NULL; } static char ssl_object_peer_certificate__doc__[] = "\n" "
\n" " Ssl\n" " peerCertificate\n" "
\n" " \n" " \n" " This method returns any peer certificate presented in the initial\n" " SSL negotiation or None. If a certificate is\n" " returned, it will be an instance of X509.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_peer_certificate(ssl_object *self, PyObject *args) { X509 *x509 = NULL; x509_object *x509_obj = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); if ((x509_obj = X509_object_new()) == NULL) lose("could not create x509 object"); x509 = SSL_get_peer_certificate(self->ssl); if (x509) { X509_free(x509_obj->x509); x509_obj->x509 = x509; return (PyObject *) x509_obj; } else { Py_XDECREF(x509_obj); Py_RETURN_NONE; } error: if (x509) X509_free(x509); Py_XDECREF(x509_obj); return NULL; } static char ssl_object_clear__doc__[] = "\n" "
\n" " Ssl\n" " clear\n" "
\n" " \n" " \n" " This method will clear the SSL session ready for\n" " a new SSL connection. It will not effect the underlying socket.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_clear(ssl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); if (!SSL_clear(self->ssl)) lose("failed to clear ssl connection"); if (self->x509_cb_err) { free(self->x509_cb_err); self->x509_cb_err = NULL; } Py_RETURN_NONE; error: return NULL; } static char ssl_object_shutdown__doc__[] = "\n" "
\n" " Ssl\n" " shutdown\n" "
\n" " \n" " \n" " This method will issue a shutdown signal to it's peer.\n" " If this connection's peer has already initiated a shutdown this call\n" " will succeed, otherwise it will raise and exception. In order to\n" " check the shutdown handshake was successful,\n" " shutdown must be called again. If no\n" " exception is raised, the handshake is complete.\n" " \n" " \n" " The odd\n" " implementation of this function reflects the underlying OpenSSL\n" " function, which reflects the SSL protocol. Although rasing an\n" " exception is a bit annoying, the alternative, returning true all\n" " false will not tell you why the call failed and the exception\n" " will, at least that is the theory. Look up the exact meaning\n" " of the exceptions in the OpenSSL man page SSL_get_error.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_shutdown(ssl_object *self, PyObject *args) { int ret = 0; if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); ret = SSL_shutdown(self->ssl); /* * The original POW behavior here seems nuts to me. SSL_shutdown() * returns a tristate: * * 1: fully closed * 0: close notification sent, waiting for peer * -1: error, WANT_READ, or WANT_WRITE * * Doc claims the protocol allows us to bail on 0 return if we don't * want to wait. So the "obvious" thing to do here is return boolean * for 1 or 0 and raise an exception for -1. Original author's explanation * for why he didn't do that makes no sense to me, so I've changed it. */ if (ret < 0) lose_ssl_error(self, ret); return PyBool_FromLong(ret); error: return NULL; } static char ssl_object_get_shutdown__doc__[] = "\n" "
\n" " Ssl\n" " getShutdown\n" "
\n" " \n" " \n" " This function returns an integer indicating the state of the\n" " SSL connection. SSL_RECEIVED_SHUTDOWN\n" " will be set the if it's peer sends a shutdown\n" " signal or the underlying socket\n" " receives a close notify . The possible values are:\n" " \n" " \n" " SSL_NO_SHUTDOWN\n" " SSL_SENT_SHUTDOWN\n" " SSL_RECEIVED_SHUTDOWN\n" " SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_get_shutdown(ssl_object *self, PyObject *args) { int state = 0; if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); state = SSL_get_shutdown(self->ssl); return Py_BuildValue("i", state); error: return NULL; } static char ssl_object_get_ciphers__doc__[] = "\n" "
\n" " Ssl\n" " getCiphers\n" "
\n" " \n" " \n" " This function returns a list of available ciphers ordered from\n" " most favored to least. This function must be called after\n" " setFd.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_get_ciphers(ssl_object *self, PyObject *args) { int i = 0; const char *cipher = NULL; PyObject *list = NULL, *name = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); list = PyList_New(0); cipher = SSL_get_cipher_list(self->ssl, 0); while (cipher) { if ((name = PyString_FromString(cipher)) == NULL) goto error; if (PyList_Append(list, name) != 0) goto error; Py_XDECREF(name); name = NULL; cipher = SSL_get_cipher_list(self->ssl, ++i); } return list; error: Py_XDECREF(name); Py_XDECREF(list); return NULL; } static char ssl_object_set_ciphers__doc__[] = "\n" "
\n" " Ssl\n" " setCiphers\n" " ciphers\n" "
\n" " \n" " \n" " setCiphers\n" " can help protect against certain types of attacks which try to\n" " coerce the server, client or both to negotiate a weak cipher.\n" " ciphers should be a list of strings, as\n" " produced by getCiphers and described in the\n" " OpenSSL man page ciphers. setCiphers should\n" " only be called after setFd.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_set_ciphers(ssl_object *self, PyObject *args) { PyObject *ciphers = NULL; PyObject *cipher = NULL; int size = 0, cipherstrlen = 0, nextstrlen = 0, i = 0; char *cipherstr = NULL; if (!PyArg_ParseTuple(args, "O", &ciphers)) goto error; if (!PyList_Check(ciphers) && !PyTuple_Check(ciphers)) lose_type_error("inapropriate type"); if (!self->ctxset) lose("cannot be called before setFd()"); cipherstr = malloc(8); // Very bogus, realloc() dosn't work without some // previously allocated memory! Really should. memset(cipherstr, 0, 8); size = PySequence_Size(ciphers); for (i = 0; i < size; i++) { if ((cipher = PySequence_GetItem(ciphers, i)) == NULL) goto error; if (!PyString_Check(cipher)) lose_type_error("inapropriate type"); cipherstrlen = strlen(cipherstr); nextstrlen = strlen(PyString_AsString(cipher)); if ((cipherstr = realloc(cipherstr, cipherstrlen + nextstrlen + 2)) == NULL) lose_type_error("could allocate memory"); if (cipherstrlen) strcat(cipherstr, ":\0"); strcat(cipherstr, PyString_AsString(cipher)); Py_XDECREF(cipher); cipher = NULL; } SSL_set_cipher_list(self->ssl, cipherstr); free(cipherstr); Py_RETURN_NONE; error: if (cipherstr) free(cipherstr); Py_XDECREF(cipher); return NULL; } static char ssl_object_get_cipher__doc__[] = "\n" "
\n" " Ssl\n" " getCipher\n" "
\n" " \n" " \n" " This function returns the current cipher in use.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_get_cipher(ssl_object *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; if (!self->ctxset) lose("cannot be called before setFd()"); return Py_BuildValue("s", SSL_get_cipher(self->ssl)); error: return NULL; } static int ssl_object_verify_callback(X509_STORE_CTX *ctx, void *arg) { ssl_object *self = arg; int ok; if (self->trusted_certs) X509_STORE_CTX_trusted_stack(ctx, self->trusted_certs); if (self->x509_cb_err) { free(self->x509_cb_err); self->x509_cb_err = NULL; } ok = X509_verify_cert(ctx) == 1; if (!ok) { /* * We probably should be pushing out structured Python data here * rather than a string, but we're pretty deep in the OpenSSL call * chain at this point and I'd rather not risk whacky interactions * with the Python garbage collector. Try this kludge initially, * rewrite as something better later if it looks worth the effort. */ BIO *b = BIO_new(BIO_s_mem()); char *buf = NULL; int len; if (!b) goto fail; BIO_puts(b, "TLS validation failure:\n\n"); if (self->trusted_certs) { int i; BIO_puts(b, "Trusted cert stack\n"); for (i = 0; i < sk_X509_num(self->trusted_certs); i++) { X509 *x = sk_X509_value(self->trusted_certs, i); BIO_printf(b, "[%d] ", i); if (x) X509_print(b, x); else BIO_puts(b, "!\n"); } } else { BIO_puts(b, "No trusted cert stack\n"); } BIO_printf(b, "\nX509_verify_cert() error: error depth %d error %d current_cert %p current_issuer %p current_crl %p: %s\n", ctx->error_depth, ctx->error, ctx->current_cert, ctx->current_issuer, ctx->current_crl, X509_verify_cert_error_string(ctx->error)); if (ctx->current_cert) X509_print(b, ctx->current_cert); /* This seems to be returning garbage, don't know why */ if (ctx->current_issuer) X509_print(b, ctx->current_issuer); if ((len = BIO_ctrl_pending(b)) == 0 || (buf = malloc(len + 1)) == NULL) goto fail; if (BIO_read(b, buf, len) == len) { buf[len] = '\0'; self->x509_cb_err = buf; } else { free(buf); } fail: BIO_free(b); } return ok; } static char ssl_object_set_verify_mode__doc__[] = "\n" "
\n" " Ssl\n" " setVerifyMode\n" " mode\n" "
\n" " \n" " \n" " This function sets the behavior of the SSL handshake. The\n" " parameter mode should be one of the\n" " following:\n" " \n" " \n" " SSL_VERIFY_NONE\n" " SSL_VERIFY_PEER\n" " SSL_VERIFY_PEER |\n" " SSL_VERIFY_FAIL_IF_NO_PEER_CERT\n" " \n" " \n" " See the OpenSSL man page SSL_CTX_set_verify\n" " for details. This function must be called after setfd\n" " has been called.\n" " \n" " \n" "
\n" ; static PyObject * ssl_object_set_verify_mode(ssl_object *self, PyObject *args) { int mode = 0; if (!PyArg_ParseTuple(args, "i", &mode)) goto error; if (self->ctxset) lose("cannot be called after setfd()"); SSL_CTX_set_verify(self->ctx, mode, NULL); Py_RETURN_NONE; error: return NULL; } static struct PyMethodDef ssl_object_methods[] = { {"useCertificate", (PyCFunction)ssl_object_use_certificate, METH_VARARGS, NULL}, {"addCertificate", (PyCFunction)ssl_object_add_certificate, METH_VARARGS, NULL}, {"addTrust", (PyCFunction)ssl_object_add_trust, METH_VARARGS, NULL}, {"useKey", (PyCFunction)ssl_object_use_key, METH_VARARGS, NULL}, {"checkKey", (PyCFunction)ssl_object_check_key, METH_VARARGS, NULL}, {"setFd", (PyCFunction)ssl_object_set_fd, METH_VARARGS, NULL}, {"fileno", (PyCFunction)ssl_object_fileno, METH_VARARGS, NULL}, {"connect", (PyCFunction)ssl_object_connect, METH_VARARGS, NULL}, {"accept", (PyCFunction)ssl_object_accept, METH_VARARGS, NULL}, {"write", (PyCFunction)ssl_object_write, METH_VARARGS, NULL}, {"read", (PyCFunction)ssl_object_read, METH_VARARGS, NULL}, {"peerCertificate", (PyCFunction)ssl_object_peer_certificate, METH_VARARGS, NULL}, {"clear", (PyCFunction)ssl_object_clear, METH_VARARGS, NULL}, {"shutdown", (PyCFunction)ssl_object_shutdown, METH_VARARGS, NULL}, {"getShutdown", (PyCFunction)ssl_object_get_shutdown, METH_VARARGS, NULL}, {"getCiphers", (PyCFunction)ssl_object_get_ciphers, METH_VARARGS, NULL}, {"setCiphers", (PyCFunction)ssl_object_set_ciphers, METH_VARARGS, NULL}, {"getCipher", (PyCFunction)ssl_object_get_cipher, METH_VARARGS, NULL}, {"setVerifyMode", (PyCFunction)ssl_object_set_verify_mode, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static ssl_object * newssl_object(int type) { ssl_object *self; const SSL_METHOD *method; if ((self = PyObject_NEW(ssl_object, &ssltype)) == NULL) goto error; self->ctxset = 0; self->ssl = NULL; self->trusted_certs = NULL; self->x509_cb_err = NULL; switch (type) { case SSLV2_SERVER_METHOD: method = SSLv2_server_method(); break; case SSLV2_CLIENT_METHOD: method = SSLv2_client_method(); break; case SSLV2_METHOD: method = SSLv2_method(); break; case SSLV3_SERVER_METHOD: method = SSLv3_server_method(); break; case SSLV3_CLIENT_METHOD: method = SSLv3_client_method(); break; case SSLV3_METHOD: method = SSLv3_method(); break; case TLSV1_SERVER_METHOD: method = TLSv1_server_method(); break; case TLSV1_CLIENT_METHOD: method = TLSv1_client_method(); break; case TLSV1_METHOD: method = TLSv1_method(); break; case SSLV23_SERVER_METHOD: method = SSLv23_server_method(); break; case SSLV23_CLIENT_METHOD: method = SSLv23_client_method(); break; case SSLV23_METHOD: method = SSLv23_method(); break; default: lose("unknown ctx method"); } if ((self->ctx = SSL_CTX_new(method)) == NULL) lose("unable to create new ctx"); SSL_CTX_set_cert_verify_callback(self->ctx, ssl_object_verify_callback, self); return self; error: Py_XDECREF(self); return NULL; } static PyObject * ssl_object_getattr(ssl_object *self, char *name) { return Py_FindMethod(ssl_object_methods, (PyObject *)self, name); } static void ssl_object_dealloc(ssl_object *self) { SSL_free(self->ssl); SSL_CTX_free(self->ctx); if (self->trusted_certs) sk_X509_pop_free(self->trusted_certs, X509_free); if (self->x509_cb_err) free(self->x509_cb_err); PyObject_Del(self); } static char ssltype__doc__[] = "\n" "
\n" " Ssl\n" "
\n" " \n" " \n" " This class provides access to the Secure Socket Layer\n" " functionality of OpenSSL. It is designed to be a simple as\n" " possible to use and is not designed for high performance\n" " applications which handle many simultaneous connections. The\n" " original motivation for writing this library was to provide a\n" " security layer for network agents written in Python, for this\n" " application, good performance with multiple concurrent connections\n" " is not an issue.\n" " \n" " \n" "
\n" ; static PyTypeObject ssltype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "Ssl", /*tp_name*/ sizeof(ssl_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ssl_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)ssl_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, ssltype__doc__ /* Documentation string */ }; /*========== ssl Object ==========*/ /*========== asymmetric Object ==========*/ static asymmetric_object * asymmetric_object_new(int cipher_type, int key_size) { asymmetric_object *self = NULL; self = PyObject_New(asymmetric_object, &asymmetrictype); if (self == NULL) goto error; if (cipher_type != RSA_CIPHER) lose("unsupported cipher"); if ((self->cipher = RSA_generate_key(key_size,RSA_F4,NULL,NULL)) == NULL) lose("could not generate key"); self->key_type = RSA_PRIVATE_KEY; self->cipher_type = RSA_CIPHER; return self; error: Py_XDECREF(self); return NULL; } static asymmetric_object * asymmetric_object_pem_read(int key_type, BIO *in, char *pass) { asymmetric_object *self = NULL; self = PyObject_New(asymmetric_object, &asymmetrictype); if (self == NULL) goto error; switch (key_type) { case RSA_PUBLIC_KEY: if ((self->cipher = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL)) == NULL) lose("could not load public key"); self->key_type = RSA_PUBLIC_KEY; self->cipher_type = RSA_CIPHER; break; case RSA_PRIVATE_KEY: if ((self->cipher = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, pass)) == NULL) lose("could not load private key"); self->key_type = RSA_PRIVATE_KEY; self->cipher_type = RSA_CIPHER; break; default: lose("unknown key type"); } return self; error: Py_XDECREF(self); return NULL; } static asymmetric_object * asymmetric_object_der_read(int key_type, unsigned char *src, int len) { asymmetric_object *self = NULL; unsigned char *ptr = src; self = PyObject_New(asymmetric_object, &asymmetrictype); if (self == NULL) goto error; switch (key_type) { case RSA_PUBLIC_KEY: if ((self->cipher = d2i_RSA_PUBKEY(NULL, (const unsigned char **) &ptr, len)) == NULL) lose("could not load public key"); self->key_type = RSA_PUBLIC_KEY; self->cipher_type = RSA_CIPHER; break; case RSA_PRIVATE_KEY: if ((self->cipher = d2i_RSAPrivateKey(NULL, (const unsigned char **) &ptr, len)) == NULL) lose("could not load private key"); self->key_type = RSA_PRIVATE_KEY; self->cipher_type = RSA_CIPHER; break; default: lose("unknown key type"); } return self; error: Py_XDECREF(self); return NULL; } static char asymmetric_object_pem_write__doc__[] = "\n" "
\n" " Asymmetric\n" " pemWrite\n" " keytype\n" " ciphertype = None\n" " passphrase = None\n" "
\n" " \n" " \n" " This method is used to write Asymmetric\n" " objects out as strings. The first argument should be either\n" " RSA_PUBLIC_KEY or\n" " RSA_PRIVATE_KEY. Private keys are often\n" " saved in encrypted files to offer extra security above access\n" " control mechanisms. If the keytype is\n" " RSA_PRIVATE_KEY a\n" " ciphertype and\n" " passphrase can also be specified. The\n" " ciphertype should be one of those listed in\n" " the Symmetric class section.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_pem_write(asymmetric_object *self, PyObject *args) { int key_type = 0, cipher = 0, len = 0, ret = 0; char *kstr = NULL, *buf = NULL; BIO *out_bio = NULL; PyObject *asymmetric = NULL; if (!PyArg_ParseTuple(args, "|iis", &key_type, &cipher, &kstr)) goto error; if (key_type == 0) key_type = self->key_type; if ((out_bio = BIO_new(BIO_s_mem())) == NULL) lose("unable to create new BIO"); if ((kstr && !cipher) || (cipher && !kstr)) lose("cipher type and key string must both be supplied"); switch(key_type) { case RSA_PRIVATE_KEY: if (kstr && cipher) { if (!PEM_write_bio_RSAPrivateKey(out_bio, self->cipher, evp_cipher_factory(cipher), NULL, 0, NULL, kstr)) lose("unable to write key"); } else { if (!PEM_write_bio_RSAPrivateKey(out_bio, self->cipher, NULL, NULL, 0, NULL, NULL)) lose("unable to write key"); } break; case RSA_PUBLIC_KEY: if (kstr && cipher) lose("public keys should not encrypted"); else { if (!PEM_write_bio_RSA_PUBKEY(out_bio, self->cipher)) lose("unable to write key"); } break; default: lose("unsupported key type"); } if ((len = BIO_ctrl_pending(out_bio)) == 0) lose("unable to get number of bytes in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if ((ret = BIO_read(out_bio, buf, len)) != len) lose("unable to write out key"); asymmetric = Py_BuildValue("s#", buf, len); BIO_free(out_bio); free(buf); return asymmetric; error: if (out_bio); BIO_free(out_bio); if (buf) free(buf); return NULL; } static char asymmetric_object_der_write__doc__[] = "" "
" " Asymmetric" " derWrite" " keytype" "
" " " " " " This method is used to write Asymmetric" " objects out as strings. The first argument should be either" " RSA_PUBLIC_KEY or " " RSA_PRIVATE_KEY." " " " " "
" ; static PyObject * asymmetric_object_der_write(asymmetric_object *self, PyObject *args) { int len = 0, key_type = 0; unsigned char *buf = NULL, *p = NULL; PyObject *asymmetric = NULL; if (!PyArg_ParseTuple(args, "|i", &key_type)) goto error; if (key_type == 0) key_type = self->key_type; switch(key_type) { case RSA_PRIVATE_KEY: len = i2d_RSAPrivateKey(self->cipher, NULL); if ((buf = malloc(len)) == NULL) lose("could not allocate memory"); p = buf; if (!i2d_RSAPrivateKey(self->cipher, &buf)) lose("unable to write key"); break; case RSA_PUBLIC_KEY: len = i2d_RSA_PUBKEY(self->cipher, NULL); if ((buf = malloc(len)) == NULL) lose("could not allocate memory"); p = buf; if (!i2d_RSA_PUBKEY(self->cipher, &buf)) lose("unable to write key"); break; default: lose("unsupported key type"); } asymmetric = Py_BuildValue("s#", p, len); free(p); return asymmetric; error: if (p) free(p); return NULL; } static char asymmetric_object_public_encrypt__doc__[] = "\n" "
\n" " Asymmetric\n" " publicEncrypt\n" " plaintext\n" "
\n" " \n" " \n" " This method is used to encrypt the plaintext\n" " using a public key. It should be noted; in practice this\n" " function would be used almost exclusively to encrypt symmetric cipher\n" " keys and not data since asymmetric cipher operations are very slow.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_public_encrypt(asymmetric_object *self, PyObject *args) { unsigned char *plain_text = NULL, *cipher_text = NULL; int len = 0, size = 0; PyObject *obj = NULL; if (self->cipher_type != RSA_CIPHER) lose("unsupported cipher type"); if (!PyArg_ParseTuple(args, "s#", &plain_text, &len)) goto error; size = RSA_size(self->cipher); if (len > size) lose("plain text is too long"); if ((cipher_text = malloc(size + 16)) == NULL) lose("could not allocate memory"); if ((len = RSA_public_encrypt(len, plain_text, cipher_text, self->cipher, RSA_PKCS1_PADDING)) < 0) lose("could not encrypt plain text"); obj = Py_BuildValue("s#", cipher_text, len); free(cipher_text); return obj; error: if (cipher_text) free(cipher_text); return NULL; } static char asymmetric_object_private_encrypt__doc__[] = "\n" "
\n" " Asymmetric\n" " privateEncrypt\n" " plaintext\n" "
\n" " \n" " \n" " This method is used to encrypt the plaintext\n" " using a private key. It should be noted; in practice this\n" " function would be used almost exclusively to encrypt symmetric cipher\n" " keys and not data since asymmetric cipher operations are very slow.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_private_encrypt(asymmetric_object *self, PyObject *args) { unsigned char *plain_text = NULL, *cipher_text = NULL; int len = 0, size = 0; PyObject *obj = NULL; if (self->key_type != RSA_PRIVATE_KEY) lose("cannot perform private encryption with this key"); if (!PyArg_ParseTuple(args, "s#", &plain_text, &len)) goto error; size = RSA_size(self->cipher); if (len > size) lose("plain text is too long"); if ((cipher_text = malloc(size + 16)) == NULL) lose("could not allocate memory"); if ((len = RSA_private_encrypt(len, plain_text, cipher_text, self->cipher, RSA_PKCS1_PADDING)) < 0) lose("could not encrypt plain text"); obj = Py_BuildValue("s#", cipher_text, len); free(cipher_text); return obj; error: if (cipher_text) free(cipher_text); return NULL; } static char asymmetric_object_public_decrypt__doc__[] = "\n" "
\n" " Asymmetric\n" " publicDecrypt\n" " ciphertext\n" "
\n" " \n" " \n" " This method is used to decrypt the\n" " ciphertext which has been encrypted\n" " using the corresponding private key and the\n" " privateEncrypt function.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_public_decrypt(asymmetric_object *self, PyObject *args) { unsigned char *plain_text = NULL, *cipher_text = NULL; int len = 0, size = 0; PyObject *obj = NULL; if (self->cipher_type != RSA_CIPHER) lose("unsupported cipher type"); if (!PyArg_ParseTuple(args, "s#", &cipher_text, &len)) goto error; size = RSA_size(self->cipher); if (len > size) lose("cipher text is too long"); if ((plain_text = malloc(size + 16)) == NULL) lose("could not allocate memory"); if ((len = RSA_public_decrypt(len, cipher_text, plain_text, self->cipher, RSA_PKCS1_PADDING)) < 0) lose("could not decrypt cipher text"); obj = Py_BuildValue("s#", plain_text, len); free(plain_text); return obj; error: if (plain_text) free(plain_text); return NULL; } static char asymmetric_object_private_decrypt__doc__[] = "\n" "
\n" " Asymmetric\n" " privateDecrypt\n" " ciphertext\n" "
\n" " \n" " \n" " This method is used to decrypt ciphertext which has been encrypted\n" " using the corresponding public key and the\n" " publicEncrypt function.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_private_decrypt(asymmetric_object *self, PyObject *args) { unsigned char *plain_text = NULL, *cipher_text = NULL; int len = 0, size = 0; PyObject *obj = NULL; if (self->key_type != RSA_PRIVATE_KEY) lose("cannot perform private decryption with this key"); if (!PyArg_ParseTuple(args, "s#", &cipher_text, &len)) goto error; size = RSA_size(self->cipher); if (len > size) lose("cipher text is too long"); if ((plain_text = malloc(size + 16)) == NULL) lose("could not allocate memory"); if ((len = RSA_private_decrypt(len, cipher_text, plain_text, self->cipher, RSA_PKCS1_PADDING)) < 0) lose("could not decrypt cipher text"); obj = Py_BuildValue("s#", plain_text, len); free(plain_text); return obj; error: if (plain_text) free(plain_text); return NULL; } static char asymmetric_object_sign__doc__[] = "\n" "
\n" " Asymmetric\n" " sign\n" " digesttext\n" " digesttype\n" "
\n" " \n" " \n" " This method is used to produce a signed digest text.\n" " This instance of\n" " Asymmetric should be a private key used for\n" " signing. The parameter\n" " digesttext should be a digest of the\n" " data to protect against alteration and\n" " finally digesttype should be one of the\n" " following:\n" " \n" " \n" #ifndef OPENSSL_NO_MD2 " MD2_DIGEST\n" #endif " MD5_DIGEST\n" " SHA_DIGEST\n" " SHA1_DIGEST\n" " RIPEMD160_DIGEST\n" " SHA256_DIGEST\n" " SHA384_DIGEST\n" " SHA512_DIGEST\n" " \n" " \n" " If the procedure was successful, a string containing the signed\n" " digest is returned.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_sign(asymmetric_object *self, PyObject *args) { unsigned char *digest_text = NULL, *signed_text = NULL; unsigned int digest_len = 0, digest_type = 0, digest_nid = 0, signed_len = 0; PyObject *obj = NULL; if (!PyArg_ParseTuple(args, "s#i", &digest_text, &digest_len, &digest_type)) goto error; if (self->key_type != RSA_PRIVATE_KEY) lose("unsupported key type"); if ((signed_text = malloc(RSA_size(self->cipher))) == NULL) lose("could not allocate memory"); switch(digest_type) { #ifndef OPENSSL_NO_MD2 case MD2_DIGEST: digest_nid = NID_md2; digest_len = MD2_DIGEST_LENGTH; break; #endif case MD5_DIGEST: digest_nid = NID_md5; digest_len = MD5_DIGEST_LENGTH; break; case SHA_DIGEST: digest_nid = NID_sha; digest_len = SHA_DIGEST_LENGTH; break; case SHA1_DIGEST: digest_nid = NID_sha1; digest_len = SHA_DIGEST_LENGTH; break; case RIPEMD160_DIGEST: digest_nid = NID_ripemd160; digest_len = RIPEMD160_DIGEST_LENGTH; break; case SHA256_DIGEST: digest_nid = NID_sha256; digest_len = SHA256_DIGEST_LENGTH; break; case SHA384_DIGEST: digest_nid = NID_sha384; digest_len = SHA384_DIGEST_LENGTH; break; case SHA512_DIGEST: digest_nid = NID_sha512; digest_len = SHA512_DIGEST_LENGTH; break; default: lose("unsupported digest"); } if (!RSA_sign(digest_nid, digest_text, digest_len, signed_text, &signed_len, self->cipher)) lose("could not sign digest"); obj = Py_BuildValue("s#", signed_text, signed_len); free(signed_text); return obj; error: if (signed_text) free(signed_text); return NULL; } static char asymmetric_object_verify__doc__[] = "\n" "
\n" " Asymmetric\n" " verify\n" " signedtext\n" " digesttext\n" " digesttype\n" "
\n" " \n" " \n" " This method is used to verify a signed digest text.\n" " \n" " \n" " <function>verify</function> method usage\n" " \n" " plain_text = 'Hello World!'\n" " print '\tPlain text:', plain_text\n" " digest = POW.Digest(POW.RIPEMD160_DIGEST)\n" " digest.update(plain_text)\n" " print '\tDigest text:', digest.digest()\n" "\n" " privateFile = open('test/private.key', 'r')\n" " privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), 'pass')\n" " privateFile.close()\n" " signed_text = privateKey.sign(digest.digest(), POW.RIPEMD160_DIGEST)\n" " print '\tSigned text:', signed_text\n" "\n" " digest2 = POW.Digest(POW.RIPEMD160_DIGEST)\n" " digest2.update(plain_text)\n" " publicFile = open('test/public.key', 'r')\n" " publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n" " publicFile.close()\n" " if publicKey.verify(signed_text, digest2.digest(), POW.RIPEMD160_DIGEST):\n" " print 'Signing verified!'\n" " else:\n" " print 'Signing gone wrong!'\n" " \n" " \n" " \n" " The parameter signedtext should be a\n" " signed digest text. This instance of\n" " Asymmetric should correspond to the private\n" " key used to sign the digest. The parameter\n" " digesttext should be a digest of the same\n" " data used to produce the signedtext and\n" " finally digesttype should be one of the\n" " following:\n" " \n" " \n" #ifndef OPENSSL_NO_MD2 " MD2_DIGEST\n" #endif " MD5_DIGEST\n" " SHA_DIGEST\n" " SHA1_DIGEST\n" " RIPEMD160_DIGEST\n" " SHA256_DIGEST\n" " SHA384_DIGEST\n" " SHA512_DIGEST\n" " \n" " \n" " If the procedure was successful, 1 is returned, otherwise 0 is\n" " returned.\n" " \n" " \n" "
\n" ; static PyObject * asymmetric_object_verify(asymmetric_object *self, PyObject *args) { unsigned char *digest_text = NULL, *signed_text = NULL; int digest_len = 0, digest_type = 0, digest_nid = 0, signed_len = 0; if (!PyArg_ParseTuple(args, "s#s#i", &signed_text, &signed_len, &digest_text, &digest_len, &digest_type)) goto error; switch (digest_type) { #ifndef OPENSSL_NO_MD2 case MD2_DIGEST: digest_len = MD2_DIGEST_LENGTH; digest_nid = NID_md2; break; #endif case MD5_DIGEST: digest_len = MD5_DIGEST_LENGTH; digest_nid = NID_md5; break; case SHA_DIGEST: digest_len = SHA_DIGEST_LENGTH; digest_nid = NID_sha; break; case SHA1_DIGEST: digest_len = SHA_DIGEST_LENGTH; digest_nid = NID_sha1; break; case RIPEMD160_DIGEST: digest_len = RIPEMD160_DIGEST_LENGTH; digest_nid = NID_ripemd160; break; case SHA256_DIGEST: digest_len = SHA256_DIGEST_LENGTH; digest_nid = NID_sha256; break; case SHA384_DIGEST: digest_len = SHA384_DIGEST_LENGTH; digest_nid = NID_sha384; break; case SHA512_DIGEST: digest_len = SHA512_DIGEST_LENGTH; digest_nid = NID_sha512; break; default: lose("unsupported digest"); } return PyBool_FromLong(RSA_verify(digest_nid, digest_text, digest_len, signed_text, signed_len, self->cipher)); error: return NULL; } static struct PyMethodDef asymmetric_object_methods[] = { {"pemWrite", (PyCFunction)asymmetric_object_pem_write, METH_VARARGS, NULL}, {"derWrite", (PyCFunction)asymmetric_object_der_write, METH_VARARGS, NULL}, {"publicEncrypt", (PyCFunction)asymmetric_object_public_encrypt, METH_VARARGS, NULL}, {"privateEncrypt", (PyCFunction)asymmetric_object_private_encrypt, METH_VARARGS, NULL}, {"privateDecrypt", (PyCFunction)asymmetric_object_private_decrypt, METH_VARARGS, NULL}, {"publicDecrypt", (PyCFunction)asymmetric_object_public_decrypt, METH_VARARGS, NULL}, {"sign", (PyCFunction)asymmetric_object_sign, METH_VARARGS, NULL}, {"verify", (PyCFunction)asymmetric_object_verify, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * asymmetric_object_getattr(asymmetric_object *self, char *name) { return Py_FindMethod(asymmetric_object_methods, (PyObject *)self, name); } static void asymmetric_object_dealloc(asymmetric_object *self, char *name) { switch(self->cipher_type) { case RSA_CIPHER: RSA_free(self->cipher); break; } PyObject_Del(self); } static char asymmetrictype__doc__[] = "\n" "
\n" " Asymmetric\n" "
\n" " \n" " \n" " This class provides access to RSA asymmetric ciphers in OpenSSL.\n" " Other ciphers will probably be supported in the future but this is\n" " not a priority.\n" " \n" " \n" "
\n" ; static PyTypeObject asymmetrictype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "Asymmetric", /*tp_name*/ sizeof(asymmetric_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)asymmetric_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)asymmetric_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, asymmetrictype__doc__ /* Documentation string */ }; /*========== asymmetric Code ==========*/ /*========== symmetric Code ==========*/ static symmetric_object * symmetric_object_new(int cipher_type) { symmetric_object *self = NULL; if ((self = PyObject_New(symmetric_object, &symmetrictype)) == NULL) goto error; self->cipher_type = cipher_type; EVP_CIPHER_CTX_init(&self->cipher_ctx); return self; error: Py_XDECREF(self); return NULL; } static char symmetric_object_encrypt_init__doc__[] = "\n" "
\n" " Symmetric\n" " encryptInit\n" " key\n" " initialvalue = ''\n" "
\n" " \n" " \n" " This method sets up the cipher object to start encrypting a stream\n" " of data. The first parameter is the key used to encrypt the\n" " data. The second, the initialvalue serves\n" " a similar purpose the the salt supplied to the Unix\n" " crypt function.\n" " The initialvalue is normally chosen at random and\n" " often transmitted with the encrypted data, its purpose is to prevent\n" " two identical plain texts resulting in two identical cipher texts.\n" " \n" " \n" "
\n" ; static PyObject * symmetric_object_encrypt_init(symmetric_object *self, PyObject *args) { unsigned char *key = NULL, *iv = NULL, nulliv [] = ""; const EVP_CIPHER *cipher = NULL; if (!PyArg_ParseTuple(args, "s|s", &key, &iv)) goto error; if (!iv) iv = nulliv; if ((cipher = evp_cipher_factory(self->cipher_type)) == NULL) lose("unsupported cipher"); if (!EVP_EncryptInit(&self->cipher_ctx, cipher, key, iv)) lose("could not initialise cipher"); Py_RETURN_NONE; error: return NULL; } static char symmetric_object_decrypt_init__doc__[] = "\n" "
\n" " Symmetric\n" " decryptInit\n" " key\n" " initialvalue = ''\n" "
\n" " \n" " \n" " This method sets up the cipher object to start decrypting a stream\n" " of data. The first value must be the key used to encrypt the\n" " data. The second parameter is the initialvalue\n" " used to encrypt the data.\n" " \n" " \n" "
\n" ; static PyObject * symmetric_object_decrypt_init(symmetric_object *self, PyObject *args) { unsigned char *key = NULL, *iv = NULL, nulliv [] = ""; const EVP_CIPHER *cipher = NULL; if (!PyArg_ParseTuple(args, "s|s", &key, &iv)) goto error; if (!iv) iv = nulliv; if ((cipher = evp_cipher_factory(self->cipher_type)) == NULL) lose("unsupported cipher"); if (!EVP_DecryptInit(&self->cipher_ctx, cipher, key, iv)) lose("could not initialise cipher"); Py_RETURN_NONE; error: return NULL; } static char symmetric_object_update__doc__[] = "\n" "
\n" " Symmetric\n" " update\n" " data\n" "
\n" " \n" " \n" " This method is used to process the bulk of data being encrypted\n" " or decrypted by the cipher object. data\n" " should be a string.\n" " \n" " \n" "
\n" ; static PyObject * symmetric_object_update(symmetric_object *self, PyObject *args) { int inl = 0, outl = 0; unsigned char *in = NULL, *out = NULL; PyObject *py_out = NULL; if (!PyArg_ParseTuple(args, "s#", &in, &inl)) goto error; if ((out = malloc(inl + EVP_CIPHER_CTX_block_size(&self->cipher_ctx))) == NULL) lose("could not allocate memory"); if (!EVP_CipherUpdate(&self->cipher_ctx, out, &outl, in, inl)) lose("could not update cipher"); if ((py_out = Py_BuildValue("s#", out, outl)) == NULL) lose("could not allocate memory"); free(out); return py_out; error: if (out) free(out); return NULL; } static char symmetric_object_final__doc__[] = "\n" "
\n" " Symmetric\n" " final\n" " size = 1024\n" "
\n" " \n" " \n" " Most ciphers are block ciphers, that is they encrypt or decrypt a block of\n" " data at a time. Often the data being processed will not fill an\n" " entire block, this method processes these half-empty blocks. A\n" " string is returned of a maximum length size.\n" " \n" " \n" "
\n" ; static PyObject * symmetric_object_final(symmetric_object *self, PyObject *args) { int outl = 0, size = 1024; unsigned char *out = NULL; PyObject *py_out = NULL; if (!PyArg_ParseTuple(args, "|i", &size)) goto error; if ((out = malloc(size + EVP_CIPHER_CTX_block_size(&self->cipher_ctx))) == NULL) lose("could not allocate memory"); if (!EVP_CipherFinal(&self->cipher_ctx, out, &outl)) lose("could not update cipher"); if ((py_out = Py_BuildValue("s#", out, outl)) == NULL) lose("could not allocate memory"); free(out); return py_out; error: if (out) free(out); return NULL; } static struct PyMethodDef symmetric_object_methods[] = { {"encryptInit", (PyCFunction)symmetric_object_encrypt_init, METH_VARARGS, NULL}, {"decryptInit", (PyCFunction)symmetric_object_decrypt_init, METH_VARARGS, NULL}, {"update", (PyCFunction)symmetric_object_update, METH_VARARGS, NULL}, {"final", (PyCFunction)symmetric_object_final, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * symmetric_object_getattr(symmetric_object *self, char *name) { return Py_FindMethod(symmetric_object_methods, (PyObject *)self, name); } static void symmetric_object_dealloc(symmetric_object *self, char *name) { PyObject_Del(self); } static char symmetrictype__doc__[] = "\n" "
\n" " Symmetric\n" "
\n" " \n" " \n" " This class provides access to all the symmetric ciphers in OpenSSL.\n" " Initialisation of the cipher structures is performed late, only\n" " when encryptInit or\n" " decryptInit is called, the\n" " constructor only records the cipher type. It is possible to reuse\n" " the Symmetric objects by calling\n" " encryptInit or decryptInit\n" " again.\n" " \n" " \n" " <classname>Symmetric</classname> class usage\n" " \n" " passphrase = 'my silly passphrase'\n" " md5 = POW.Digest(POW.MD5_DIGEST)\n" " md5.update(passphrase)\n" " password = md5.digest()[:8]\n" "\n" " plaintext = 'cast test message'\n" " cast = POW.Symmetric(POW.CAST5_CFB)\n" " cast.encryptInit(password)\n" " ciphertext = cast.update(plaintext) + cast.final()\n" " print 'Cipher text:', ciphertext\n" "\n" " cast.decryptInit(password)\n" " out = cast.update(ciphertext) + cast.final()\n" " print 'Deciphered text:', out\n" " \n" " \n" " \n" "
\n" ; static PyTypeObject symmetrictype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "Symmetric", /*tp_name*/ sizeof(symmetric_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)symmetric_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)symmetric_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, symmetrictype__doc__ /* Documentation string */ }; /*========== symmetric Code ==========*/ /*========== digest Code ==========*/ static digest_object * digest_object_new(int digest_type) { digest_object *self = NULL; if ((self = PyObject_New(digest_object, &digesttype)) == NULL) goto error; switch(digest_type) { #ifndef OPENSSL_NO_MD2 case MD2_DIGEST: self->digest_type = MD2_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_md2()); break; #endif case MD5_DIGEST: self->digest_type = MD5_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_md5()); break; case SHA_DIGEST: self->digest_type = SHA_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_sha()); break; case SHA1_DIGEST: self->digest_type = SHA1_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_sha1()); break; case RIPEMD160_DIGEST: self->digest_type = RIPEMD160_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_ripemd160()); break; case SHA256_DIGEST: self->digest_type = SHA256_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_sha256()); break; case SHA384_DIGEST: self->digest_type = SHA384_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_sha384()); break; case SHA512_DIGEST: self->digest_type = SHA512_DIGEST; EVP_DigestInit(&self->digest_ctx, EVP_sha512()); break; default: lose("unsupported digest"); } return self; error: Py_XDECREF(self); return NULL; } static char digest_object_update__doc__[] = "\n" "
\n" " Digest\n" " update\n" " data\n" "
\n" " \n" " \n" " This method updates the internal structures of the\n" " Digest object with data.\n" " data should be a string.\n" " \n" " \n" "
\n" ; static PyObject * digest_object_update(digest_object *self, PyObject *args) { char *data = NULL; int len = 0; if (!PyArg_ParseTuple(args, "s#", &data, &len)) goto error; EVP_DigestUpdate(&self->digest_ctx, data, len); Py_RETURN_NONE; error: return NULL; } static char digest_object_copy__doc__[] = "\n" "
\n" " Digest\n" " copy\n" "
\n" " \n" " \n" " This method returns a copy of the Digest\n" " object.\n" " \n" " \n" "
\n" ; static PyObject * digest_object_copy(digest_object *self, PyObject *args) { digest_object *new = NULL; if ((new = PyObject_New(digest_object, &digesttype)) == NULL) lose("could not allocate memory"); new->digest_type = self->digest_type; if (!EVP_MD_CTX_copy(&new->digest_ctx, &self->digest_ctx)) lose("could not copy digest"); return (PyObject*)new; error: Py_XDECREF(new); return NULL; } static char digest_object_digest__doc__[] = "\n" "
\n" " Digest\n" " digest\n" "
\n" " \n" " \n" " This method returns the digest of all the data which has been\n" " processed. This function can be called at any time and will not\n" " effect the internal structure of the digest\n" " object.\n" " \n" " \n" "
\n" ; static PyObject * digest_object_digest(digest_object *self, PyObject *args) { unsigned char digest_text[EVP_MAX_MD_SIZE]; void *md_copy = NULL; unsigned digest_len = 0; if (!PyArg_ParseTuple(args, "")) goto error; if ((md_copy = malloc(sizeof(EVP_MD_CTX))) == NULL) lose("could not allocate memory"); if (!EVP_MD_CTX_copy(md_copy, &self->digest_ctx)) lose("could not copy digest"); EVP_DigestFinal(md_copy, digest_text, &digest_len); free(md_copy); return Py_BuildValue("s#", digest_text, digest_len); error: if (md_copy) free(md_copy); return NULL; } static struct PyMethodDef digest_object_methods[] = { {"update", (PyCFunction)digest_object_update, METH_VARARGS, NULL}, {"digest", (PyCFunction)digest_object_digest, METH_VARARGS, NULL}, {"copy", (PyCFunction)digest_object_copy, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * digest_object_getattr(digest_object *self, char *name) { return Py_FindMethod(digest_object_methods, (PyObject *)self, name); } static void digest_object_dealloc(digest_object *self, char *name) { EVP_MD_CTX_cleanup(&self->digest_ctx); PyObject_Del(self); } static char digesttype__doc__[] = "\n" "
\n" " Digest\n" "
\n" " \n" " \n" " This class provides access to the digest functionality of OpenSSL.\n" " It emulates the digest modules in the Python Standard Library but\n" " does not currently support the hexdigest\n" " function.\n" " \n" " \n" " <classname>digest</classname> class usage\n" " \n" " plain_text = 'Hello World!'\n" " sha1 = POW.Digest(POW.SHA1_DIGEST)\n" " sha1.update(plain_text)\n" " print '\tPlain text: Hello World! =>', sha1.digest()\n" " \n" " \n" " \n" "
\n" ; static PyTypeObject digesttype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "Digest", /*tp_name*/ sizeof(digest_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)digest_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)digest_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, digesttype__doc__ /* Documentation string */ }; /*========== digest Code ==========*/ /*========== hmac Code ==========*/ static hmac_object * hmac_object_new(int digest_type, char *key, int key_len) { hmac_object *self = NULL; const EVP_MD *md = NULL; if ((self = PyObject_New(hmac_object, &hmactype)) == NULL) goto error; switch (digest_type) { #ifndef OPENSSL_NO_MD2 case MD2_DIGEST: md = EVP_md2(); break; #endif case MD5_DIGEST: md = EVP_md5(); break; case SHA_DIGEST: md = EVP_sha(); break; case SHA1_DIGEST: md = EVP_sha1(); break; case RIPEMD160_DIGEST: md = EVP_ripemd160(); break; case SHA256_DIGEST: md = EVP_sha256(); break; case SHA384_DIGEST: md = EVP_sha384(); break; case SHA512_DIGEST: md = EVP_sha512(); break; default: lose("unsupported digest"); } HMAC_Init(&self->hmac_ctx, key, key_len, md); return self; error: Py_XDECREF(self); return NULL; } static char hmac_object_update__doc__[] = "\n" "
\n" " Hmac\n" " update\n" " data\n" "
\n" " \n" " \n" " This method updates the internal structures of the\n" " Hmac object with data.\n" " data should be a string.\n" " \n" " \n" "
\n" ; static PyObject * hmac_object_update(hmac_object *self, PyObject *args) { unsigned char *data = NULL; int len = 0; if (!PyArg_ParseTuple(args, "s#", &data, &len)) goto error; HMAC_Update(&self->hmac_ctx, data, len); Py_RETURN_NONE; error: return NULL; } static char hmac_object_copy__doc__[] = "\n" "
\n" " Hmac\n" " copy\n" "
\n" " \n" " \n" " This method returns a copy of the Hmac\n" " object.\n" " \n" " \n" "
\n" ; static PyObject * hmac_object_copy(hmac_object *self, PyObject *args) { hmac_object *new = NULL; if ((new = PyObject_New(hmac_object, &hmactype)) == NULL) lose("could not allocate memory"); memcpy(&new->hmac_ctx, &self->hmac_ctx, sizeof(HMAC_CTX)); return (PyObject*) new; error: Py_XDECREF(new); return NULL; } static char hmac_object_mac__doc__[] = "\n" "
\n" " Hmac\n" " mac\n" "
\n" " \n" " \n" " This method returns the MAC of all the data which has been\n" " processed. This function can be called at any time and will not\n" " effect the internal structure of the Hmac\n" " object.\n" " \n" " \n" "
\n" ; static PyObject * hmac_object_mac(hmac_object *self, PyObject *args) { unsigned char hmac_text[EVP_MAX_MD_SIZE]; void *hmac_copy = NULL; unsigned int hmac_len = 0; if (!PyArg_ParseTuple(args, "")) goto error; if ((hmac_copy = malloc(sizeof(HMAC_CTX))) == NULL) lose("could not allocate memory"); memcpy(hmac_copy, &self->hmac_ctx, sizeof(HMAC_CTX)); HMAC_Final(hmac_copy, hmac_text, &hmac_len); free(hmac_copy); return Py_BuildValue("s#", hmac_text, hmac_len); error: if (hmac_copy) free(hmac_copy); return NULL; } static struct PyMethodDef hmac_object_methods[] = { {"update", (PyCFunction)hmac_object_update, METH_VARARGS, NULL}, {"mac", (PyCFunction)hmac_object_mac, METH_VARARGS, NULL}, {"copy", (PyCFunction)hmac_object_copy, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * hmac_object_getattr(hmac_object *self, char *name) { return Py_FindMethod(hmac_object_methods, (PyObject *)self, name); } static void hmac_object_dealloc(hmac_object *self, char *name) { PyObject_Del(self); } static char hmactype__doc__[] = "\n" "
\n" " Hmac\n" "
\n" " \n" " \n" " This class provides access to the HMAC functionality of OpenSSL.\n" " HMAC's are a variant on digest based MACs, which have the\n" " interesting property of a provable level of security. HMAC is\n" " discussed further in RFC 2104.\n" " \n" " \n" "
\n" ; static PyTypeObject hmactype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "Hmac", /*tp_name*/ sizeof(hmac_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)hmac_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)hmac_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, hmactype__doc__ /* Documentation string */ }; /*========== hmac Code ==========*/ /*========== CMS code ==========*/ static cms_object * CMS_object_new(void) { cms_object *self; if ((self = PyObject_New(cms_object, &cmstype)) == NULL) goto error; self->cms = NULL; return self; error: Py_XDECREF(self); return NULL; } static cms_object * CMS_object_pem_read(BIO *in) { cms_object *self; if ((self = PyObject_New(cms_object, &cmstype)) == NULL) goto error; if ((self->cms = PEM_read_bio_CMS(in, NULL, NULL, NULL)) == NULL) lose("could not load PEM encoded CMS message"); return self; error: Py_XDECREF(self); return NULL; } static cms_object * CMS_object_der_read(char *src, int len) { cms_object *self; BIO *bio = NULL; if ((self = PyObject_New(cms_object, &cmstype)) == NULL) goto error; self->cms = CMS_ContentInfo_new(); if ((bio = BIO_new_mem_buf(src, len)) == NULL) goto error; if (!d2i_CMS_bio(bio, &self->cms)) lose("could not load DER encoded CMS message"); BIO_free(bio); return self; error: if (bio) BIO_free(bio); Py_XDECREF(self); return NULL; } static PyObject * CMS_object_write_helper(cms_object *self, PyObject *args, int format) { int len = 0; char *buf = NULL; BIO *out_bio = NULL; PyObject *cert = NULL; if (!PyArg_ParseTuple(args, "")) return NULL; out_bio = BIO_new(BIO_s_mem()); switch (format) { case DER_FORMAT: if (!i2d_CMS_bio(out_bio, self->cms)) lose("unable to write certificate"); break; case PEM_FORMAT: if (!PEM_write_bio_CMS(out_bio, self->cms)) lose("unable to write certificate"); break; default: lose("internal error, unknown output format"); } if ((len = BIO_ctrl_pending(out_bio)) == 0) lose("unable to get bytes stored in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if (BIO_read(out_bio, buf, len) != len) lose("unable to write out cert"); cert = Py_BuildValue("s#", buf, len); BIO_free(out_bio); free(buf); return cert; error: if (out_bio) BIO_free(out_bio); if (buf) free(buf); Py_XDECREF(cert); return NULL; } static char CMS_object_pem_write__doc__[] = "\n" "
\n" " CMS\n" " pemWrite\n" "
\n" " \n" " \n" " This method returns a PEM encoded CMS message as a\n" " string.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_pem_write(cms_object *self, PyObject *args) { return CMS_object_write_helper(self, args, PEM_FORMAT); } static char CMS_object_der_write__doc__[] = "\n" "
\n" " CMS\n" " derWrite\n" "
\n" " \n" " \n" " This method returns a DER encoded CMS message as a\n" " string.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_der_write(cms_object *self, PyObject *args) { return CMS_object_write_helper(self, args, DER_FORMAT); } static char CMS_object_sign__doc__[] = "\n" "
\n" " CMS\n" " sign\n" " signcert\n" " key\n" " data\n" " \n" " certs\n" " crls\n" " eContentType\n" " flags\n" " \n" "
\n" " \n" " \n" " This method signs a message with a private key.\n" " Supported flags: CMS_NOCERTS, CMS_NOATTR.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_sign(cms_object *self, PyObject *args) { asymmetric_object *signkey = NULL; x509_object *signcert = NULL; x509_crl_object *crlobj = NULL; PyObject *x509_sequence = Py_None, *crl_sequence = Py_None, *result = NULL; STACK_OF(X509) *x509_stack = NULL; EVP_PKEY *pkey = NULL; char *buf = NULL, *oid = NULL; int i, n, len; unsigned flags = 0; BIO *bio = NULL; CMS_ContentInfo *cms = NULL; ASN1_OBJECT *econtent_type = NULL; if (!PyArg_ParseTuple(args, "O!O!s#|OOsI", &x509type, &signcert, &asymmetrictype, &signkey, &buf, &len, &x509_sequence, &crl_sequence, &oid, &flags)) goto error; assert_no_unhandled_openssl_errors(); flags &= CMS_NOCERTS | CMS_NOATTR; flags |= CMS_BINARY | CMS_NOSMIMECAP | CMS_PARTIAL | CMS_USE_KEYID; if (signkey->key_type != RSA_PRIVATE_KEY) lose("unsupported key type"); if ((x509_stack = x509_helper_sequence_to_stack(x509_sequence)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if ((pkey = EVP_PKEY_new()) == NULL) lose_openssl_error("Could not allocate memory"); assert_no_unhandled_openssl_errors(); if (!EVP_PKEY_assign_RSA(pkey, signkey->cipher)) lose_openssl_error("EVP_PKEY assignment error"); assert_no_unhandled_openssl_errors(); if ((bio = BIO_new_mem_buf(buf, len)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if (oid && (econtent_type = OBJ_txt2obj(oid, 0)) == NULL) lose_openssl_error("Could not parse OID"); assert_no_unhandled_openssl_errors(); if ((cms = CMS_sign(NULL, NULL, x509_stack, bio, flags)) == NULL) lose_openssl_error("Could not create CMS message"); assert_no_unhandled_openssl_errors(); if (econtent_type) CMS_set1_eContentType(cms, econtent_type); assert_no_unhandled_openssl_errors(); if (!CMS_add1_signer(cms, signcert->x509, pkey, EVP_sha256(), flags)) lose_openssl_error("Could not sign CMS message"); pkey = NULL; /* CMS_add1_signer() now owns pkey */ assert_no_unhandled_openssl_errors(); if (crl_sequence != Py_None) { if (!PyTuple_Check(crl_sequence) && !PyList_Check(crl_sequence)) lose_type_error("inapropriate type"); n = PySequence_Size(crl_sequence); for (i = 0; i < n; i++) { if ((crlobj = (x509_crl_object *) PySequence_GetItem(crl_sequence, i)) == NULL) goto error; if (!X_X509_crl_Check(crlobj)) lose_type_error("inappropriate type"); if (!crlobj->crl) lose("CRL object with null crl field!"); if (!CMS_add1_crl(cms, crlobj->crl)) lose_openssl_error("Could not add CRL to CMS"); assert_no_unhandled_openssl_errors(); Py_XDECREF(crlobj); crlobj = NULL; } } if (!CMS_final(cms, bio, NULL, flags)) lose_openssl_error("Could not finalize CMS signatures"); assert_no_unhandled_openssl_errors(); if (self->cms) CMS_ContentInfo_free(self->cms); self->cms = cms; cms = NULL; result = Py_BuildValue(""); error: /* fall through */ assert_no_unhandled_openssl_errors(); if (cms) CMS_ContentInfo_free(cms); if (bio) BIO_free(bio); if (x509_stack) sk_X509_free(x509_stack); if (pkey) EVP_PKEY_free(pkey); if (econtent_type) ASN1_OBJECT_free(econtent_type); if (crlobj) { Py_XDECREF(crlobj); } return result; } static char CMS_object_verify__doc__[] = "\n" "
\n" " CMS\n" " verify\n" " store\n" " \n" " certs\n" " flags\n" " \n" "
\n" " \n" " \n" " This method verifies a message against a trusted store.\n" " The optional certs parameter is a set of certificates to search\n" " for the signer's certificate.\n" " Supported flags: CMS_NOINTERN, CMS_NOCRL,\n" " CMS_NO_SIGNER_CERT_VERIFY, CMS_NO_ATTR_VERIFY,\n" " CMS_NO_CONTENT_VERIFY.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_verify(cms_object *self, PyObject *args) { x509_store_object *store = NULL; PyObject *result = NULL, *certs_sequence = Py_None; STACK_OF(X509) *certs_stack = NULL; unsigned flags = 0; char *buf = NULL; BIO *bio = NULL; int len; if (!PyArg_ParseTuple(args, "O!|OI", &x509_storetype, &store, &certs_sequence, &flags)) goto error; if ((bio = BIO_new(BIO_s_mem())) == NULL) goto error; assert_no_unhandled_openssl_errors(); flags &= CMS_NOINTERN | CMS_NOCRL | CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY | CMS_NO_CONTENT_VERIFY; if (certs_sequence != Py_None && (certs_stack = x509_helper_sequence_to_stack(certs_sequence)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if (CMS_verify(self->cms, certs_stack, store->store, NULL, bio, flags) <= 0) lose_openssl_error("Could not verify CMS message"); assert_no_unhandled_openssl_errors(); if ((len = BIO_ctrl_pending(bio)) == 0) lose("unable to get bytes stored in bio"); assert_no_unhandled_openssl_errors(); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); assert_no_unhandled_openssl_errors(); if (BIO_read(bio, buf, len) != len) lose("unable to write out CMS content"); assert_no_unhandled_openssl_errors(); result = Py_BuildValue("s#", buf, len); error: /* fall through */ assert_no_unhandled_openssl_errors(); if (certs_stack) sk_X509_free(certs_stack); if (bio) BIO_free(bio); if (buf) free(buf); return result; } static char CMS_object_eContentType__doc__[] = "\n" "
\n" " CMS\n" " get_eContentType\n" "
\n" " \n" " \n" " This method returns the eContentType of a CMS message.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_eContentType(cms_object *self, PyObject *args) { const ASN1_OBJECT *oid = NULL; PyObject *result = NULL; char buf[512]; if (!PyArg_ParseTuple(args, "")) return NULL; if ((oid = CMS_get0_eContentType(self->cms)) == NULL) lose_openssl_error("Could not extract eContentType from CMS message"); OBJ_obj2txt(buf, sizeof(buf), oid, 1); result = Py_BuildValue("s", buf); error: assert_no_unhandled_openssl_errors(); return result; } static char CMS_object_signingTime__doc__[] = "\n" "
\n" " CMS\n" " get_signingTime\n" "
\n" " \n" " \n" " This method returns the signingTime of a CMS message.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_signingTime(cms_object *self, PyObject *args) { PyObject *result = NULL; STACK_OF(CMS_SignerInfo) *sis = NULL; CMS_SignerInfo *si = NULL; X509_ATTRIBUTE *xa = NULL; ASN1_TYPE *so = NULL; int i; if (!PyArg_ParseTuple(args, "")) return NULL; if ((sis = CMS_get0_SignerInfos(self->cms)) == NULL) lose("Could not extract signerInfos from CMS message[1]"); if (sk_CMS_SignerInfo_num(sis) != 1) lose("Could not extract signerInfos from CMS message[2]"); si = sk_CMS_SignerInfo_value(sis, 0); if ((i = CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1)) < 0) lose("Could not extract signerInfos from CMS message[3]"); if ((xa = CMS_signed_get_attr(si, i)) == NULL) lose("Could not extract signerInfos from CMS message[4]"); if (xa->single) lose("Could not extract signerInfos from CMS message[5]"); if (sk_ASN1_TYPE_num(xa->value.set) != 1) lose("Could not extract signerInfos from CMS message[6]"); if ((so = sk_ASN1_TYPE_value(xa->value.set, 0)) == NULL) lose("Could not extract signerInfos from CMS message[7]"); switch (so->type) { case V_ASN1_UTCTIME: result = ASN1_TIME_to_Python(so->value.utctime); break; case V_ASN1_GENERALIZEDTIME: result = ASN1_TIME_to_Python(so->value.generalizedtime); break; default: lose("Could not extract signerInfos from CMS message[8]"); } error: assert_no_unhandled_openssl_errors(); return result; } static char CMS_object_pprint__doc__[] = "\n" "
\n" " CMS\n" " pprint\n" "
\n" " \n" " \n" " This method returns a formatted string showing the information\n" " held in the certificate.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_pprint(cms_object *self, PyObject *args) { int len = 0, ret = 0; char *buf = NULL; BIO *bio = NULL; PyObject *result = NULL; if (!PyArg_ParseTuple(args, "")) goto error; bio = BIO_new(BIO_s_mem()); if (!CMS_ContentInfo_print_ctx(bio, self->cms, 0, NULL)) lose("unable to pprint CMS"); if ((len = BIO_ctrl_pending(bio)) == 0) lose("unable to get bytes stored in bio"); if ((buf = malloc(len)) == NULL) lose("unable to allocate memory"); if ((ret = BIO_read(bio, buf, len)) != len) lose("unable to pprint CMS"); result = Py_BuildValue("s#", buf, len); error: /* fall through */ assert_no_unhandled_openssl_errors(); if (bio) BIO_free(bio); if (buf) free(buf); return result; } static PyObject * cms_object_helper_get_cert(void *cert) { x509_object *obj = PyObject_New(x509_object, &x509type); if (obj) obj->x509 = cert; return (PyObject *) obj; } static char CMS_object_certs__doc__[] = "\n" "
\n" " CMS\n" " certs\n" "
\n" " \n" " \n" " This method returns any certs embedded in a CMS message.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_certs(cms_object *self, PyObject *args) { STACK_OF(X509) *certs = NULL; PyObject *result = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if ((certs = CMS_get1_certs(self->cms)) != NULL) result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509), certs), cms_object_helper_get_cert); else if (!ERR_peek_error()) result = Py_BuildValue("()"); else lose_openssl_error("Could not extract certs from CMS message"); error: /* fall through */ if (certs) sk_X509_pop_free(certs, X509_free); return result; } static PyObject * cms_object_helper_get_crl(void *crl) { x509_crl_object *obj = PyObject_New(x509_crl_object, &x509_crltype); if (obj) obj->crl = crl; return (PyObject *) obj; } static char CMS_object_crls__doc__[] = "\n" "
\n" " CMS\n" " crls\n" "
\n" " \n" " \n" " This method returns any CRLs embedded in a CMS message.\n" " \n" " \n" "
\n" ; static PyObject * CMS_object_crls(cms_object *self, PyObject *args) { STACK_OF(X509_CRL) *crls = NULL; PyObject *result = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if ((crls = CMS_get1_crls(self->cms)) != NULL) result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509_CRL), crls), cms_object_helper_get_crl); else if (!ERR_peek_error()) result = Py_BuildValue("()"); else lose_openssl_error("Could not extract CRLs from CMS message"); error: /* fall through */ if (crls) sk_X509_CRL_pop_free(crls, X509_CRL_free); return result; } static struct PyMethodDef CMS_object_methods[] = { {"pemWrite", (PyCFunction)CMS_object_pem_write, METH_VARARGS, NULL}, {"derWrite", (PyCFunction)CMS_object_der_write, METH_VARARGS, NULL}, {"sign", (PyCFunction)CMS_object_sign, METH_VARARGS, NULL}, {"verify", (PyCFunction)CMS_object_verify, METH_VARARGS, NULL}, {"eContentType", (PyCFunction)CMS_object_eContentType, METH_VARARGS, NULL}, {"signingTime", (PyCFunction)CMS_object_signingTime, METH_VARARGS, NULL}, {"pprint", (PyCFunction)CMS_object_pprint, METH_VARARGS, NULL}, {"certs", (PyCFunction)CMS_object_certs, METH_VARARGS, NULL}, {"crls", (PyCFunction)CMS_object_crls, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; static PyObject * CMS_object_getattr(cms_object *self, char *name) { return Py_FindMethod(CMS_object_methods, (PyObject *)self, name); } static void CMS_object_dealloc(cms_object *self, char *name) { CMS_ContentInfo_free(self->cms); PyObject_Del(self); } static char cmstype__doc__[] = "\n" "
\n" " CMS\n" "
\n" " \n" " \n" " This class provides basic access OpenSSL's CMS functionality.\n" " \n" " \n" "
\n" ; static PyTypeObject cmstype = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "CMS", /*tp_name*/ sizeof(cms_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CMS_object_dealloc, /*tp_dealloc*/ (printfunc)0, /*tp_print*/ (getattrfunc)CMS_object_getattr, /*tp_getattr*/ (setattrfunc)0, /*tp_setattr*/ (cmpfunc)0, /*tp_compare*/ (reprfunc)0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ 0, 0, 0, 0, cmstype__doc__ /* Documentation string */ }; /*========== CMS Code ==========*/ /*========== module functions ==========*/ static char pow_module_new_ssl__doc__[] = "\n" "
\n" " Ssl\n" " protocol = SSLV23METHOD\n" "
\n" " \n" " \n" " This constructor creates a new Ssl object which will behave as a client\n" " or server, depending on the protocol value passed. The\n" " protocol also determines the protocol type\n" " and version and should be one of the following:\n" " \n" "\n" " \n" " SSLV2_SERVER_METHOD\n" " SSLV2_CLIENT_METHOD\n" " SSLV2_METHOD\n" " SSLV3_SERVER_METHOD\n" " SSLV3_CLIENT_METHOD\n" " SSLV3_METHOD\n" " TLSV1_SERVER_METHOD\n" " TLSV1_CLIENT_METHOD\n" " TLSV1_METHOD\n" " SSLV23_SERVER_METHOD\n" " SSLV23_CLIENT_METHOD\n" " SSLV23_METHOD\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_ssl (PyObject *self, PyObject *args) { ssl_object *ssl = NULL; int ctxtype = SSLV23_METHOD; if (!PyArg_ParseTuple(args, "|i", &ctxtype)) goto error; if ((ssl = newssl_object(ctxtype)) == NULL) goto error; return (PyObject*) ssl; error: return NULL; } static char pow_module_new_x509__doc__[] = "\n" "
\n" " X509\n" "
\n" " \n" " \n" " This constructor creates a skeletal X509 certificate object.\n" " It won't be any use at all until several structures\n" " have been created using it's member functions.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_x509 (PyObject *self, PyObject *args) { x509_object *x509 = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if ((x509 = X509_object_new()) == NULL) lose("could not create new x509 object"); return (PyObject*)x509; error: return NULL; } static char pow_module_new_asymmetric__doc__[] = "\n" "
\n" " Asymmetric\n" " ciphertype = RSA_CIPHER\n" " keylength = 1024\n" "
\n" " \n" " \n" " This constructor builds a new cipher object. Only RSA ciphers\n" " are currently support, so the first argument should always be\n" " RSA_CIPHER. The second argument,\n" " keylength,\n" " is normally 512, 768, 1024 or 2048. Key lengths as short as 512\n" " bits are generally considered weak, and can be cracked by\n" " determined attackers without tremendous expense.\n" " \n" " \n" " <classname>asymmetric</classname> class usage\n" " \n" " privateFile = open('test/private.key', 'w')\n" " publicFile = open('test/public.key', 'w')\n" "\n" " passphrase = 'my silly passphrase'\n" " md5 = POW.Digest(POW.MD5_DIGEST)\n" " md5.update(passphrase)\n" " password = md5.digest()\n" "\n" " rsa = POW.Asymmetric(POW.RSA_CIPHER, 1024)\n" " privateFile.write(rsa.pemWrite(\n" " POW.RSA_PRIVATE_KEY, POW.DES_EDE3_CFB, password))\n" " publicFile.write(rsa.pemWrite(POW.RSA_PUBLIC_KEY))\n" "\n" " privateFile.close()\n" " publicFile.close()\n" " \n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_asymmetric (PyObject *self, PyObject *args) { int cipher_type = RSA_CIPHER, key_size = 1024; if (!PyArg_ParseTuple(args, "|ii", &cipher_type, &key_size)) goto error; return (PyObject*) asymmetric_object_new(cipher_type, key_size); error: return NULL; } static char pow_module_new_digest__doc__[] = "\n" "
\n" " Digest\n" " type\n" "
\n" " \n" " \n" " This constructor creates a new Digest\n" " object. The parameter type specifies what kind\n" " of digest to create and should be one of the following:\n" " \n" " \n" #ifndef OPENSSL_NO_MD2 " MD2_DIGEST\n" #endif " MD5_DIGEST\n" " SHA_DIGEST\n" " SHA1_DIGEST\n" " RIPEMD160_DIGEST\n" " SHA256_DIGEST\n" " SHA384_DIGEST\n" " SHA512_DIGEST\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_digest (PyObject *self, PyObject *args) { int digest_type = 0; if (!PyArg_ParseTuple(args, "i", &digest_type)) goto error; return (PyObject*) digest_object_new(digest_type); error: return NULL; } static char pow_module_new_hmac__doc__[] = "\n" "
\n" " Hmac\n" " type\n" " key\n" "
\n" " \n" " \n" " This constructor creates a new Hmac\n" " object. The parameter key should be a\n" " string and type should be one of the following:\n" " \n" " \n" #ifndef OPENSSL_NO_MD2 " MD2_DIGEST\n" #endif " MD5_DIGEST\n" " SHA_DIGEST\n" " SHA1_DIGEST\n" " RIPEMD160_DIGEST\n" " SHA256_DIGEST\n" " SHA384_DIGEST\n" " SHA512_DIGEST\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_hmac (PyObject *self, PyObject *args) { int digest_type = 0, key_len = 0; char *key = NULL; if (!PyArg_ParseTuple(args, "is#", &digest_type, &key, &key_len)) goto error; return (PyObject*) hmac_object_new(digest_type, key, key_len); error: return NULL; } static char pow_module_new_cms__doc__[] = "\n" "
\n" " CMS\n" "
\n" " \n" " \n" " This constructor creates a skeletal CMS object.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_cms (PyObject *self, PyObject *args) { cms_object *cms = NULL; if (!PyArg_ParseTuple(args, "")) goto error; if ((cms = CMS_object_new()) == NULL) lose("could not create new CMS object"); return (PyObject*)cms; error: return NULL; } static char pow_module_pem_read__doc__[] = "\n" "
\n" " pemRead\n" " type\n" " string\n" " pass = None\n" "
\n" " \n" " \n" " This function attempts to parse the string according to the PEM\n" " type passed. type should be one of the\n" " following:\n" " \n" " \n" " RSA_PUBLIC_KEY\n" " RSA_PRIVATE_KEY\n" " X509_CERTIFICATE\n" " X509_CRL\n" " CMS_MESSAGE\n" " \n" " \n" " pass should only be provided if an encrypted\n" " Asymmetric is being loaded. If the password\n" " is incorrect an exception will be raised, if no password is provided\n" " and the PEM file is encrypted the user will be prompted. If this is\n" " not desirable, always supply a password. The object returned will be\n" " and instance of Asymmetric,\n" " X509, X509Crl,\n" " or CMS.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_pem_read (PyObject *self, PyObject *args) { BIO *in = NULL; PyObject *obj = NULL; int object_type = 0, len = 0; char *pass = NULL, *src = NULL; if (!PyArg_ParseTuple(args, "is#|s", &object_type, &src, &len, &pass)) goto error; if ((in = BIO_new_mem_buf(src, len)) == NULL) lose("unable to create new BIO"); switch(object_type) { case RSA_PRIVATE_KEY: obj = (PyObject*)asymmetric_object_pem_read(object_type, in, pass); break; case RSA_PUBLIC_KEY: obj = (PyObject*)asymmetric_object_pem_read(object_type, in, pass); break; case X509_CERTIFICATE: obj = (PyObject*)X509_object_pem_read(in); break; case X_X509_CRL: obj = (PyObject*)x509_crl_object_pem_read(in); break; case CMS_MESSAGE: obj = (PyObject*)CMS_object_pem_read(in); break; default: lose("unknown pem encoding"); } BIO_free(in); if (obj) return obj; error: return NULL; } static char pow_module_der_read__doc__[] = "\n" "
\n" " derRead\n" " type\n" " string\n" "
\n" " \n" " \n" " This function attempts to parse the string according to the PEM\n" " type passed. type should be one of the\n" " following:\n" " \n" " \n" " RSA_PUBLIC_KEY\n" " RSA_PRIVATE_KEY\n" " X509_CERTIFICATE\n" " X509_CRL\n" " CMS_MESSAGE\n" " \n" " \n" " As with the PEM operations, the object returned will be and instance\n" " of Asymmetric, X509,\n" " X509Crl, or CMS.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_der_read (PyObject *self, PyObject *args) { PyObject *obj = NULL; int object_type = 0, len = 0; unsigned char *src = NULL; if (!PyArg_ParseTuple(args, "is#", &object_type, &src, &len)) goto error; switch(object_type) { case RSA_PRIVATE_KEY: obj = (PyObject*) asymmetric_object_der_read(object_type, src, len); break; case RSA_PUBLIC_KEY: obj = (PyObject*) asymmetric_object_der_read(object_type, src, len); break; case X509_CERTIFICATE: obj = (PyObject*)X509_object_der_read(src, len); break; case X_X509_CRL: obj = (PyObject*)x509_crl_object_der_read(src, len); break; case CMS_MESSAGE: obj = (PyObject*)CMS_object_der_read((char *) src, len); break; default: lose("unknown der encoding"); } if (obj) return obj; error: return NULL; } static char pow_module_new_x509_store__doc__[] = "\n" "
\n" " X509Store\n" "
\n" " \n" " \n" " This constructor takes no arguments. The\n" " X509Store returned cannot be used for\n" " verifying certificates until at least one trusted certificate has been\n" " added.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_x509_store (PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return (PyObject *) x509_store_object_new(); error: return NULL; } static char pow_module_new_symmetric__doc__[] = "\n" "
\n" " Symmetric\n" " type\n" "
\n" " \n" " \n" " This constructor creates a new Symmetric\n" " object. The parameter type specifies which kind\n" " of cipher to create. type should be one of the following:\n" " \n" " \n" " DES_ECB\n" " DES_EDE\n" " DES_EDE3\n" " DES_CFB\n" " DES_EDE_CFB\n" " DES_EDE3_CFB\n" " DES_OFB\n" " DES_EDE_OFB\n" " DES_EDE3_OFB\n" " DES_CBC\n" " DES_EDE_CBC\n" " DES_EDE3_CBC\n" " DESX_CBC\n" " RC4\n" " RC4_40\n" " IDEA_ECB\n" " IDEA_CFB\n" " IDEA_OFB\n" " IDEA_CBC\n" " RC2_ECB\n" " RC2_CBC\n" " RC2_40_CBC\n" " RC2_CFB\n" " RC2_OFB\n" " BF_ECB\n" " BF_CBC\n" " BF_CFB\n" " BF_OFB\n" " CAST5_ECB\n" " CAST5_CBC\n" " CAST5_CFB\n" " CAST5_OFB\n" " RC5_32_12_16_CBC\n" " RC5_32_12_16_CFB\n" " RC5_32_12_16_ECB\n" " RC5_32_12_16_OFB\n" " \n" " \n" " Please note your version of OpenSSL might not have been compiled with\n" " all the ciphers listed above. If that is the case, which is very\n" " likely if you are using a stock binary, the unsuported ciphers will not even\n" " be in the module namespace.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_symmetric (PyObject *self, PyObject *args) { int cipher_type = 0; if (!PyArg_ParseTuple(args, "i", &cipher_type)) goto error; return (PyObject *) symmetric_object_new(cipher_type); error: return NULL; } static char pow_module_new_x509_crl__doc__[] = "\n" "
\n" " x509_crl\n" "
\n" " \n" " \n" " This constructor builds an empty CRL.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_x509_crl (PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; return (PyObject *) x509_crl_object_new(); error: return NULL; } static char pow_module_new_x509_revoked__doc__[] = "\n" "
\n" " X509Revoked\n" " serial\n" " date\n" "
\n" " \n" " \n" " This constructor builds a X509 Revoked structure. serial\n" " should be an integer and date should be and\n" " UTCTime string.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_new_x509_revoked (PyObject *self, PyObject *args) { int serial = -1; char *date = NULL; x509_revoked_object *revoke = NULL; if (!PyArg_ParseTuple(args, "|is", &serial, &date)) goto error; revoke = x509_revoked_object_new(); if (serial != -1 && !ASN1_INTEGER_set(revoke->revoked->serialNumber, serial)) lose("unable to set serial number"); if (date != NULL && !python_ASN1_TIME_set_string(revoke->revoked->revocationDate, date)) lose_type_error("Could not set revocationDate"); return (PyObject*) revoke; error: return NULL; } static char pow_module_add_object__doc__[] = "\n" "
\n" " addObject\n" " oid\n" " shortName\n" " longName\n" "
\n" " \n" " \n" " This function can be used to dynamically add new objects to\n" " OpenSSL. The oid should be a string of space separated numbers\n" " and shortName and\n" " longName are the names of the object, ie\n" " 'cn' and 'commonName'.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_add_object(PyObject *self, PyObject *args) { char *oid = NULL, *sn = NULL, *ln = NULL; if (!PyArg_ParseTuple(args, "sss", &oid, &sn, &ln)) goto error; if (!OBJ_create(oid, sn, ln)) lose("unable to add object"); Py_RETURN_NONE; error: return NULL; } static char pow_module_get_error__doc__[] = "\n" "
\n" " getError\n" "
\n" " \n" " \n" " Pops an error off the global error stack and returns it as a string.\n" " Returns None if the global error stack is empty.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_get_error(PyObject *self, PyObject *args) { unsigned long error; char buf[256]; if (!PyArg_ParseTuple(args, "")) goto error; error = ERR_get_error(); if (!error) Py_RETURN_NONE; ERR_error_string_n(error, buf, sizeof(buf)); return Py_BuildValue("s", buf); error: return NULL; } static char pow_module_clear_error__doc__[] = "\n" "
\n" " clearError\n" "
\n" " \n" " \n" " Removes all errors from the global error stack.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_clear_error(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) goto error; ERR_clear_error(); Py_RETURN_NONE; error: return NULL; } static char pow_module_seed__doc__[] = "\n" "
\n" " seed\n" " data\n" "
\n" " \n" " \n" " The seed function adds data to OpenSSLs PRNG\n" " state. It is often said the hardest part of cryptography is\n" " getting good random data, after all if you don't have good random\n" " data, a 1024 bit key is no better than a 512 bit key and neither\n" " would provide protection from a targeted brute force attack.\n" " The seed and add are very\n" " similar, except the entropy of the data is assumed to be equal to\n" " the length for seed. One final point to be aware\n" " of, only systems which support /dev/urandom are automatically seeded.\n" " If your system does not support /dev/urandom it is your responsibility\n" " to seed OpenSSL's PRNG.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_seed(PyObject *self, PyObject *args) { char *in = NULL; int inl = 0; if (!PyArg_ParseTuple(args, "s#", &in, &inl)) goto error; RAND_seed(in, inl); Py_RETURN_NONE; error: return NULL; } static char pow_module_add__doc__[] = "\n" "
\n" " add\n" " data\n" " entropy\n" "
\n" " \n" " \n" " The add function adds data to OpenSSLs PRNG\n" " state. data should be data obtained from a\n" " random source and entropy is an estimation of the number of random\n" " bytes in data.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_add(PyObject *self, PyObject *args) { char *in = NULL; int inl = 0; double entropy = 0; if (!PyArg_ParseTuple(args, "s#d", &in, &inl, &entropy)) goto error; RAND_add(in, inl, entropy); Py_RETURN_NONE; error: return NULL; } static char pow_module_write_random_file__doc__[] = "\n" "
\n" " writeRandomFile\n" " filename\n" "
\n" " \n" " \n" " This function writes the current random state to a file. Clearly\n" " this function should be used in conjunction with\n" " readRandomFile.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_write_random_file(PyObject *self, PyObject *args) { char *file = NULL; if (!PyArg_ParseTuple(args, "s", &file)) goto error; if (RAND_write_file(file) == -1) lose("could not write random file"); Py_RETURN_NONE; error: return NULL; } static char pow_module_read_random_file__doc__[] = "\n" "
\n" " readRandomFile\n" " filename\n" "
\n" " \n" " \n" " This function reads a previously saved random state. It can be very\n" " useful to improve the quality of random data used by an application.\n" " The random data should be added to, using the\n" " add function, with data from other\n" " suitable random sources.\n" " \n" " \n" "
\n" ; static PyObject * pow_module_read_random_file(PyObject *self, PyObject *args) { char *file = NULL; int len = -1; if (!PyArg_ParseTuple(args, "s|i", &file, &len)) goto error; if (!RAND_load_file(file, len)) lose("could not load random file"); Py_RETURN_NONE; error: return NULL; } static PyObject * pow_module_docset(PyObject *self, PyObject *args) { PyObject *docset; if (!PyArg_ParseTuple(args, "")) goto error; docset = PyList_New(0); // module documentation docset_helper_add(docset, pow_module__doc__); // constructors docset_helper_add(docset, pow_module_new_symmetric__doc__); docset_helper_add(docset, pow_module_new_asymmetric__doc__); docset_helper_add(docset, pow_module_new_digest__doc__); docset_helper_add(docset, pow_module_new_hmac__doc__); docset_helper_add(docset, pow_module_new_ssl__doc__); docset_helper_add(docset, pow_module_new_x509__doc__); docset_helper_add(docset, pow_module_new_x509_store__doc__); docset_helper_add(docset, pow_module_new_x509_crl__doc__); docset_helper_add(docset, pow_module_new_x509_revoked__doc__); docset_helper_add(docset, pow_module_new_cms__doc__); // functions docset_helper_add(docset, pow_module_pem_read__doc__); docset_helper_add(docset, pow_module_der_read__doc__); docset_helper_add(docset, pow_module_seed__doc__); docset_helper_add(docset, pow_module_add__doc__); docset_helper_add(docset, pow_module_read_random_file__doc__); docset_helper_add(docset, pow_module_write_random_file__doc__); docset_helper_add(docset, pow_module_get_error__doc__); docset_helper_add(docset, pow_module_clear_error__doc__); docset_helper_add(docset, pow_module_add_object__doc__); // ssl documentation docset_helper_add(docset, ssltype__doc__); docset_helper_add(docset, ssl_object_set_fd__doc__); docset_helper_add(docset, ssl_object_fileno__doc__); docset_helper_add(docset, ssl_object_accept__doc__); docset_helper_add(docset, ssl_object_connect__doc__); docset_helper_add(docset, ssl_object_write__doc__); docset_helper_add(docset, ssl_object_read__doc__); docset_helper_add(docset, ssl_object_peer_certificate__doc__); docset_helper_add(docset, ssl_object_use_certificate__doc__); docset_helper_add(docset, ssl_object_use_key__doc__); docset_helper_add(docset, ssl_object_check_key__doc__); docset_helper_add(docset, ssl_object_clear__doc__); docset_helper_add(docset, ssl_object_shutdown__doc__); docset_helper_add(docset, ssl_object_get_shutdown__doc__); docset_helper_add(docset, ssl_object_get_ciphers__doc__); docset_helper_add(docset, ssl_object_set_ciphers__doc__); docset_helper_add(docset, ssl_object_get_cipher__doc__); docset_helper_add(docset, ssl_object_set_verify_mode__doc__); // x509 documentation docset_helper_add(docset, x509type__doc__); docset_helper_add(docset, X509_object_pem_write__doc__); docset_helper_add(docset, X509_object_der_write__doc__); docset_helper_add(docset, X509_object_sign__doc__); docset_helper_add(docset, X509_object_set_public_key__doc__); docset_helper_add(docset, X509_object_get_version__doc__); docset_helper_add(docset, X509_object_set_version__doc__); docset_helper_add(docset, X509_object_get_serial__doc__); docset_helper_add(docset, X509_object_set_serial__doc__); docset_helper_add(docset, X509_object_get_issuer__doc__); docset_helper_add(docset, X509_object_set_issuer__doc__); docset_helper_add(docset, X509_object_get_subject__doc__); docset_helper_add(docset, X509_object_set_subject__doc__); docset_helper_add(docset, X509_object_get_not_before__doc__); docset_helper_add(docset, X509_object_set_not_before__doc__); docset_helper_add(docset, X509_object_get_not_after__doc__); docset_helper_add(docset, X509_object_set_not_after__doc__); docset_helper_add(docset, X509_object_add_extension__doc__); docset_helper_add(docset, X509_object_clear_extensions__doc__); docset_helper_add(docset, X509_object_count_extensions__doc__); docset_helper_add(docset, X509_object_get_extension__doc__); docset_helper_add(docset, x509_object_pprint__doc__); // x509_crl documentation docset_helper_add(docset, x509_crltype__doc__); docset_helper_add(docset, x509_crl_object_pem_write__doc__); docset_helper_add(docset, x509_crl_object_der_write__doc__); docset_helper_add(docset, x509_crl_object_get_version__doc__); docset_helper_add(docset, x509_crl_object_set_version__doc__); docset_helper_add(docset, x509_crl_object_get_issuer__doc__); docset_helper_add(docset, x509_crl_object_set_issuer__doc__); docset_helper_add(docset, x509_crl_object_get_this_update__doc__); docset_helper_add(docset, x509_crl_object_set_this_update__doc__); docset_helper_add(docset, x509_crl_object_get_next_update__doc__); docset_helper_add(docset, x509_crl_object_set_next_update__doc__); docset_helper_add(docset, x509_crl_object_get_revoked__doc__); docset_helper_add(docset, x509_crl_object_set_revoked__doc__); docset_helper_add(docset, x509_crl_object_verify__doc__); docset_helper_add(docset, x509_crl_object_sign__doc__); docset_helper_add(docset, X509_crl_object_add_extension__doc__); docset_helper_add(docset, X509_crl_object_clear_extensions__doc__); docset_helper_add(docset, X509_crl_object_count_extensions__doc__); docset_helper_add(docset, X509_crl_object_get_extension__doc__); docset_helper_add(docset, x509_crl_object_pprint__doc__); // x509_revoked documentation docset_helper_add(docset, x509_revokedtype__doc__); docset_helper_add(docset, x509_revoked_object_get_date__doc__); docset_helper_add(docset, x509_revoked_object_set_date__doc__); docset_helper_add(docset, x509_revoked_object_get_serial__doc__); docset_helper_add(docset, x509_revoked_object_set_serial__doc__); docset_helper_add(docset, X509_revoked_object_add_extension__doc__); docset_helper_add(docset, X509_revoked_object_clear_extensions__doc__); docset_helper_add(docset, X509_revoked_object_count_extensions__doc__); docset_helper_add(docset, X509_revoked_object_get_extension__doc__); // x509_store documentation docset_helper_add(docset, x509_storetype__doc__); docset_helper_add(docset, x509_store_object_verify__doc__); docset_helper_add(docset, x509_store_object_verify_chain__doc__); docset_helper_add(docset, x509_store_object_verify_detailed__doc__); docset_helper_add(docset, x509_store_object_add_trust__doc__); docset_helper_add(docset, x509_store_object_add_crl__doc__); // digest documentation docset_helper_add(docset, digesttype__doc__); docset_helper_add(docset, digest_object_update__doc__); docset_helper_add(docset, digest_object_copy__doc__); docset_helper_add(docset, digest_object_digest__doc__); // hmac documentation docset_helper_add(docset, hmactype__doc__); docset_helper_add(docset, hmac_object_update__doc__); docset_helper_add(docset, hmac_object_copy__doc__); docset_helper_add(docset, hmac_object_mac__doc__); // cms documentation docset_helper_add(docset, CMS_object_pem_write__doc__); docset_helper_add(docset, CMS_object_der_write__doc__); docset_helper_add(docset, CMS_object_sign__doc__); docset_helper_add(docset, CMS_object_verify__doc__); docset_helper_add(docset, CMS_object_eContentType__doc__); docset_helper_add(docset, CMS_object_signingTime__doc__); docset_helper_add(docset, CMS_object_pprint__doc__); docset_helper_add(docset, CMS_object_certs__doc__); docset_helper_add(docset, CMS_object_crls__doc__); // symmetric documentation docset_helper_add(docset, symmetrictype__doc__); docset_helper_add(docset, symmetric_object_encrypt_init__doc__); docset_helper_add(docset, symmetric_object_decrypt_init__doc__); docset_helper_add(docset, symmetric_object_update__doc__); docset_helper_add(docset, symmetric_object_final__doc__); // asymmetric documentation docset_helper_add(docset, asymmetrictype__doc__); docset_helper_add(docset, asymmetric_object_pem_write__doc__); docset_helper_add(docset, asymmetric_object_der_write__doc__); docset_helper_add(docset, asymmetric_object_public_encrypt__doc__); docset_helper_add(docset, asymmetric_object_public_decrypt__doc__); docset_helper_add(docset, asymmetric_object_private_encrypt__doc__); docset_helper_add(docset, asymmetric_object_private_decrypt__doc__); docset_helper_add(docset, asymmetric_object_sign__doc__); docset_helper_add(docset, asymmetric_object_verify__doc__); return docset; error: return NULL; } static struct PyMethodDef pow_module_methods[] = { {"Ssl", (PyCFunction)pow_module_new_ssl, METH_VARARGS, NULL}, {"X509", (PyCFunction)pow_module_new_x509, METH_VARARGS, NULL}, {"pemRead", (PyCFunction)pow_module_pem_read, METH_VARARGS, NULL}, {"derRead", (PyCFunction)pow_module_der_read, METH_VARARGS, NULL}, {"Digest", (PyCFunction)pow_module_new_digest, METH_VARARGS, NULL}, {"Hmac", (PyCFunction)pow_module_new_hmac, METH_VARARGS, NULL}, {"CMS", (PyCFunction)pow_module_new_cms, METH_VARARGS, NULL}, {"Asymmetric", (PyCFunction)pow_module_new_asymmetric, METH_VARARGS, NULL}, {"Symmetric", (PyCFunction)pow_module_new_symmetric, METH_VARARGS, NULL}, {"X509Store", (PyCFunction)pow_module_new_x509_store, METH_VARARGS, NULL}, {"X509Crl", (PyCFunction)pow_module_new_x509_crl, METH_VARARGS, NULL}, {"X509Revoked", (PyCFunction)pow_module_new_x509_revoked, METH_VARARGS, NULL}, {"getError", (PyCFunction)pow_module_get_error, METH_VARARGS, NULL}, {"clearError", (PyCFunction)pow_module_clear_error, METH_VARARGS, NULL}, {"seed", (PyCFunction)pow_module_seed, METH_VARARGS, NULL}, {"add", (PyCFunction)pow_module_add, METH_VARARGS, NULL}, {"readRandomFile", (PyCFunction)pow_module_read_random_file, METH_VARARGS, NULL}, {"writeRandomFile", (PyCFunction)pow_module_write_random_file, METH_VARARGS, NULL}, {"addObject", (PyCFunction)pow_module_add_object, METH_VARARGS, NULL}, {"_docset", (PyCFunction)pow_module_docset, METH_VARARGS, NULL}, {NULL} /* sentinel */ }; /*========== module functions ==========*/ /*==========================================================================*/ void init_POW(void) { PyObject *m; x509type.ob_type = &PyType_Type; x509_storetype.ob_type = &PyType_Type; x509_crltype.ob_type = &PyType_Type; x509_revokedtype.ob_type = &PyType_Type; ssltype.ob_type = &PyType_Type; asymmetrictype.ob_type = &PyType_Type; symmetrictype.ob_type = &PyType_Type; digesttype.ob_type = &PyType_Type; hmactype.ob_type = &PyType_Type; cmstype.ob_type = &PyType_Type; m = Py_InitModule3("_POW", pow_module_methods, pow_module__doc__); #define Define_Exception(__name__, __parent__) \ PyModule_AddObject(m, #__name__, ((__name__##Object) = PyErr_NewException("POW." #__name__, __parent__, NULL))) Define_Exception(Error, NULL); Define_Exception(SSLError, ErrorObject); Define_Exception(ZeroReturnError, SSLErrorObject); Define_Exception(WantReadError, SSLErrorObject); Define_Exception(WantWriteError, SSLErrorObject); Define_Exception(SSLSyscallError, SSLErrorObject); Define_Exception(SSLErrorSSLError, SSLErrorObject); Define_Exception(SSLSyscallSSLError, SSLErrorObject); Define_Exception(SSLUnexpectedEOFError,SSLErrorObject); Define_Exception(SSLOtherError, SSLErrorObject); #undef Define_Exception #define Define_Integer_Constant(__name__) \ PyModule_AddIntConstant(m, #__name__, __name__) // constants for SSL_get_error() Define_Integer_Constant(SSL_ERROR_NONE); Define_Integer_Constant(SSL_ERROR_ZERO_RETURN); Define_Integer_Constant(SSL_ERROR_WANT_READ); Define_Integer_Constant(SSL_ERROR_WANT_WRITE); Define_Integer_Constant(SSL_ERROR_WANT_X509_LOOKUP); Define_Integer_Constant(SSL_ERROR_SYSCALL); Define_Integer_Constant(SSL_ERROR_SSL); Define_Integer_Constant(SSL_ERROR_WANT_CONNECT); Define_Integer_Constant(SSL_ERROR_WANT_ACCEPT); // constants for different types of connection methods Define_Integer_Constant(SSLV2_SERVER_METHOD); Define_Integer_Constant(SSLV2_CLIENT_METHOD); Define_Integer_Constant(SSLV2_METHOD); Define_Integer_Constant(SSLV3_SERVER_METHOD); Define_Integer_Constant(SSLV3_CLIENT_METHOD); Define_Integer_Constant(SSLV3_METHOD); Define_Integer_Constant(SSLV23_SERVER_METHOD); Define_Integer_Constant(SSLV23_CLIENT_METHOD); Define_Integer_Constant(SSLV23_METHOD); Define_Integer_Constant(TLSV1_SERVER_METHOD); Define_Integer_Constant(TLSV1_CLIENT_METHOD); Define_Integer_Constant(TLSV1_METHOD); Define_Integer_Constant(SSL_NO_SHUTDOWN); Define_Integer_Constant(SSL_SENT_SHUTDOWN); Define_Integer_Constant(SSL_RECEIVED_SHUTDOWN); // ssl verification mode Define_Integer_Constant(SSL_VERIFY_NONE); Define_Integer_Constant(SSL_VERIFY_PEER); Define_Integer_Constant(SSL_VERIFY_FAIL_IF_NO_PEER_CERT); Define_Integer_Constant(SSL_VERIFY_CLIENT_ONCE); // object format types Define_Integer_Constant(LONGNAME_FORMAT); Define_Integer_Constant(SHORTNAME_FORMAT); // PEM encoded types #ifndef OPENSSL_NO_RSA Define_Integer_Constant(RSA_PUBLIC_KEY); Define_Integer_Constant(RSA_PRIVATE_KEY); #endif #ifndef OPENSSL_NO_DSA Define_Integer_Constant(DSA_PUBLIC_KEY); Define_Integer_Constant(DSA_PRIVATE_KEY); #endif #ifndef OPENSSL_NO_DH Define_Integer_Constant(DH_PUBLIC_KEY); Define_Integer_Constant(DH_PRIVATE_KEY); #endif Define_Integer_Constant(X509_CERTIFICATE); PyModule_AddIntConstant(m, "X509_CRL", X_X509_CRL); Define_Integer_Constant(CMS_MESSAGE); // asymmetric ciphers #ifndef OPENSSL_NO_RSA Define_Integer_Constant(RSA_CIPHER); #endif #ifndef OPENSSL_NO_DSA Define_Integer_Constant(DSA_CIPHER); #endif #ifndef OPENSSL_NO_DH Define_Integer_Constant(DH_CIPHER); #endif // symmetric ciphers #ifndef OPENSSL_NO_DES Define_Integer_Constant(DES_ECB); Define_Integer_Constant(DES_EDE); Define_Integer_Constant(DES_EDE3); Define_Integer_Constant(DES_CFB); Define_Integer_Constant(DES_EDE_CFB); Define_Integer_Constant(DES_EDE3_CFB); Define_Integer_Constant(DES_OFB); Define_Integer_Constant(DES_EDE_OFB); Define_Integer_Constant(DES_EDE3_OFB); Define_Integer_Constant(DES_CBC); Define_Integer_Constant(DES_EDE_CBC); Define_Integer_Constant(DES_EDE3_CBC); Define_Integer_Constant(DESX_CBC); #endif #ifndef OPENSSL_NO_RC4 Define_Integer_Constant(RC4); Define_Integer_Constant(RC4_40); #endif #ifndef OPENSSL_NO_IDEA Define_Integer_Constant(IDEA_ECB); Define_Integer_Constant(IDEA_CFB); Define_Integer_Constant(IDEA_OFB); Define_Integer_Constant(IDEA_CBC); #endif #ifndef OPENSSL_NO_RC2 Define_Integer_Constant(RC2_ECB); Define_Integer_Constant(RC2_CBC); Define_Integer_Constant(RC2_40_CBC); Define_Integer_Constant(RC2_CFB); Define_Integer_Constant(RC2_OFB); #endif #ifndef OPENSSL_NO_BF Define_Integer_Constant(BF_ECB); Define_Integer_Constant(BF_CBC); Define_Integer_Constant(BF_CFB); Define_Integer_Constant(BF_OFB); #endif Define_Integer_Constant(CAST5_ECB); Define_Integer_Constant(CAST5_CBC); Define_Integer_Constant(CAST5_CFB); Define_Integer_Constant(CAST5_OFB); #ifndef OPENSSL_NO_RC5 Define_Integer_Constant(RC5_32_12_16_CBC); Define_Integer_Constant(RC5_32_12_16_CFB); Define_Integer_Constant(RC5_32_12_16_ECB); Define_Integer_Constant(RC5_32_12_16_OFB); #endif // message digests #ifndef OPENSSL_NO_MD2 Define_Integer_Constant(MD2_DIGEST); #endif Define_Integer_Constant(MD5_DIGEST); Define_Integer_Constant(SHA_DIGEST); Define_Integer_Constant(SHA1_DIGEST); Define_Integer_Constant(RIPEMD160_DIGEST); Define_Integer_Constant(SHA256_DIGEST); Define_Integer_Constant(SHA384_DIGEST); Define_Integer_Constant(SHA512_DIGEST); // general name Define_Integer_Constant(GEN_OTHERNAME); Define_Integer_Constant(GEN_EMAIL); Define_Integer_Constant(GEN_DNS); Define_Integer_Constant(GEN_X400); Define_Integer_Constant(GEN_DIRNAME); Define_Integer_Constant(GEN_EDIPARTY); Define_Integer_Constant(GEN_URI); Define_Integer_Constant(GEN_IPADD); Define_Integer_Constant(GEN_RID); // CMS flags Define_Integer_Constant(CMS_NOCERTS); Define_Integer_Constant(CMS_NOATTR); Define_Integer_Constant(CMS_NOINTERN); Define_Integer_Constant(CMS_NOCRL); Define_Integer_Constant(CMS_NO_SIGNER_CERT_VERIFY); Define_Integer_Constant(CMS_NO_ATTR_VERIFY); Define_Integer_Constant(CMS_NO_CONTENT_VERIFY); #undef Define_Integer_Constant // initialise library SSL_library_init(); OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); // load error strings SSL_load_error_strings(); if (PyErr_Occurred()) Py_FatalError("Can't initialize module POW"); } /*==========================================================================*/ /* * Local Variables: * indent-tabs-mode: nil * End: */