Prepare for 0.14 release git-svn-id: svn://10.0.0.236/trunk@264395 18797224-902f-48f8-a5cc-f745e15eee43
22834 lines
693 KiB
C
22834 lines
693 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* FIXME - below are general things which need fixing
|
|
*
|
|
* repr() vs. str() class methods. repr should just use the default of
|
|
* printing out the object class name and object pointer, not the contents
|
|
* of the object, that's the role of str().
|
|
*
|
|
* When receiving string parameters via PyArg_ParseTuple*() we should
|
|
* allow both str and unicode objects and encode unicode to UTF-8
|
|
* this would be done by changing the 's' format specifier to 'es'
|
|
* and adding a 'utf-8' parameter prior to the string address parameter.
|
|
* Unlike the 's' format specifier the char pointer will need to be
|
|
* freed because it's copy of the encoded string.
|
|
*
|
|
* We should consider setting the default encoding to UTF-8 when our
|
|
* module loads. This is global and would affect all other modules loaded
|
|
* into the Python application. At the moment the default is 'ascii' which
|
|
* breaks anything which is expecting a sane default.
|
|
*/
|
|
|
|
#if 0
|
|
|
|
//Template for new classes
|
|
|
|
/* ========================================================================== */
|
|
/* ============================= NewType Class ============================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
NewType_get_classproperty(NewType *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int
|
|
NewType_set_classproperty(NewType *self, PyObject *value, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the classproperty attribute");
|
|
return -1;
|
|
}
|
|
|
|
if (!PyString_Check(value)) {
|
|
PyErr_Format(PyExc_TypeError, "classproperty must be a string, not %.200s",
|
|
Py_TYPE(value)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef NewType_getseters[] = {
|
|
{"classproperty", (getter)NewType_get_classproperty, (setter)NewType_set_classproperty,
|
|
"xxx", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef NewType_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
NewType_format_lines(NewType *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
SECOidTag alg_tag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
NewType_format(NewType *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)NewType_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
NewType_str(NewType *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = NewType_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(NewType_func_name_doc,
|
|
"func_name() -> \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
arg1 : object\n\
|
|
xxx\n\
|
|
\n\
|
|
xxx\n\
|
|
");
|
|
|
|
static PyObject *
|
|
NewType_func_name(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"arg1", NULL};
|
|
PyObject *arg;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:func_name", kwlist,
|
|
&arg))
|
|
return NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static PyMethodDef NewType_methods[] = {
|
|
{"format_lines", (PyCFunction)NewType_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)NewType_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{"func_name", (PyCFunction)NewType_func_name, METH_VARARGS|METH_KEYWORDS, NewType_func_name_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Sequence Protocol ============================ */
|
|
static Py_ssize_t
|
|
NSSType_list_count(NSSType *head)
|
|
{
|
|
NSSType *cur;
|
|
Py_ssize_t count;
|
|
|
|
count = 0;
|
|
if (!head) {
|
|
return count;
|
|
}
|
|
|
|
cur = head;
|
|
do {
|
|
count++;
|
|
cur = NSSType_Next(cur);
|
|
} while (cur != head);
|
|
|
|
return count;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
NewType_length(NewType *self)
|
|
{
|
|
if (!self->name) {
|
|
PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
return NSSType_list_count(self->name);
|
|
}
|
|
|
|
static PyObject *
|
|
NewType_item(NewType *self, register Py_ssize_t i)
|
|
{
|
|
NSSType *head, *cur;
|
|
Py_ssize_t index;
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
index = 0;
|
|
cur = head = self->name;
|
|
do {
|
|
cur = NSSType_Next(cur);
|
|
if (i == index) {
|
|
return NewType_new_from_NSSType(cur);
|
|
}
|
|
index++;
|
|
} while (cur != head);
|
|
|
|
PyErr_SetString(PyExc_IndexError, "NewType index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
NewType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
NewType *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (NewType *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
Py_TPFLAGS_HAVE_GC
|
|
static int
|
|
NewType_traverse(NewType *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->obj);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
NewType_clear(NewType* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->obj);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
NewType_dealloc(NewType* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
NewType_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(NewType_doc,
|
|
"NewType(obj)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
obj : xxx\n\
|
|
\n\
|
|
An object representing NewType.\n\
|
|
");
|
|
|
|
static int
|
|
NewType_init(NewType *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"arg", NULL};
|
|
PyObject *arg;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:NewType", kwlist,
|
|
&arg))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PySequenceMethods NewType_as_sequence = {
|
|
(lenfunc)NewType_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)NewType_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyTypeObject NewTypeType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.NewType", /* tp_name */
|
|
sizeof(NewType), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)NewType_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)NewType_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
NewType_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
NewType_methods, /* tp_methods */
|
|
NewType_members, /* tp_members */
|
|
NewType_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)NewType_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
NewType_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
NewType_new_from_NSSType(NSSType *id)
|
|
{
|
|
NewType *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (NewType *) NewTypeType.tp_new(&NewTypeType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
#endif
|
|
|
|
// FIXME: should we be calling these?
|
|
// SECKEY_DestroyEncryptedPrivateKeyInfo
|
|
// SECKEY_DestroyPrivateKey SECKEY_DestroyPrivateKeyInfo
|
|
// SECKEY_DestroyPrivateKeyList SECKEY_DestroyPublicKey
|
|
// SECKEY_DestroyPublicKeyList SECKEY_DestroySubjectPublicKeyInfo
|
|
|
|
#define CERT_DecodeDERCertificate __CERT_DecodeDERCertificate
|
|
|
|
#define PY_SSIZE_T_CLEAN
|
|
#include "Python.h"
|
|
#include "structmember.h"
|
|
|
|
#include "py_nspr_common.h"
|
|
#define NSS_NSS_MODULE
|
|
#include "py_nss.h"
|
|
#include "py_nspr_error.h"
|
|
|
|
#include "secder.h"
|
|
#include "sechash.h"
|
|
#include "certdb.h"
|
|
#include "hasht.h"
|
|
#include "nssb64.h"
|
|
#include "secport.h"
|
|
#include "secerr.h"
|
|
#include "secpkcs5.h"
|
|
#include "p12plcy.h"
|
|
#include "ciferfam.h"
|
|
|
|
#if (NSS_VMAJOR > 3) || (NSS_VMAJOR == 3 && NSS_VMINOR >= 13)
|
|
#define HAVE_RSA_PSS
|
|
#endif
|
|
|
|
#define MAX_AVAS 10
|
|
#define MAX_RDNS 10
|
|
#define OCTETS_PER_LINE_DEFAULT 16
|
|
#define HEX_SEPARATOR_DEFAULT ":"
|
|
|
|
/* FIXME: convert all equality tests to Py_None to PyNone_Check() */
|
|
|
|
//FIXME, should be in py_nss.h
|
|
#define PyAVA_Check(op) PyObject_TypeCheck(op, &AVAType)
|
|
#define PyRDN_Check(op) PyObject_TypeCheck(op, &RDNType)
|
|
#define PyDN_Check(op) PyObject_TypeCheck(op, &DNType)
|
|
|
|
#define PyRSAGenParams_Check(op) PyObject_TypeCheck(op, &RSAGenParamsType)
|
|
#define PyKEYPQGParams_Check(op) PyObject_TypeCheck(op, &KEYPQGParamsType)
|
|
#define PyCertVerifyLog_Check(op) PyObject_TypeCheck(op, &CertVerifyLogType)
|
|
|
|
|
|
#define BIT_FLAGS_TO_LIST_PROLOGUE() \
|
|
PyObject *py_flags = NULL; \
|
|
PyObject *py_flag = NULL; \
|
|
\
|
|
switch(repr_kind) { \
|
|
case AsEnum: \
|
|
case AsEnumName: \
|
|
case AsEnumDescription: \
|
|
break; \
|
|
default: \
|
|
PyErr_Format(PyExc_ValueError, "Unsupported representation kind (%d)", repr_kind); \
|
|
return NULL; \
|
|
} \
|
|
\
|
|
if ((py_flags = PyList_New(0)) == NULL) \
|
|
return NULL;
|
|
|
|
|
|
|
|
#define BIT_FLAGS_TO_LIST(enum, description) \
|
|
{ \
|
|
if (flags & enum) { \
|
|
flags &= ~enum; \
|
|
switch(repr_kind) { \
|
|
case AsEnum: \
|
|
py_flag = PyInt_FromLong(enum); \
|
|
break; \
|
|
case AsEnumName: \
|
|
py_flag = PyString_FromString(#enum); \
|
|
break; \
|
|
case AsEnumDescription: \
|
|
py_flag = PyString_FromString(description); \
|
|
break; \
|
|
default: \
|
|
PyErr_Format(PyExc_ValueError, "Unsupported representation kind (%d)", repr_kind); \
|
|
Py_DECREF(py_flags); \
|
|
return NULL; \
|
|
} \
|
|
if (py_flag == NULL) { \
|
|
Py_DECREF(py_flags); \
|
|
return NULL; \
|
|
} \
|
|
PyList_Append(py_flags, py_flag); \
|
|
Py_DECREF(py_flag); \
|
|
} \
|
|
}
|
|
|
|
#define BIT_FLAGS_TO_LIST_EPILOGUE() \
|
|
{ \
|
|
if (flags) { \
|
|
if ((py_flag = PyString_FromFormat("unknown bit flags %#x", flags)) == NULL) { \
|
|
Py_DECREF(py_flags); \
|
|
return NULL; \
|
|
} \
|
|
PyList_Append(py_flags, py_flag); \
|
|
Py_DECREF(py_flag); \
|
|
} \
|
|
\
|
|
if (PyList_Sort(py_flags) == -1) { \
|
|
Py_DECREF(py_flags); \
|
|
return NULL; \
|
|
} \
|
|
\
|
|
return py_flags; \
|
|
}
|
|
|
|
// FIXME, should use this in more places.
|
|
PyObject *
|
|
PyString_UTF8(PyObject *obj, char *name);
|
|
|
|
|
|
#define SECITEM_PARAM(py_param, pitem, tmp_item, none_ok, param_name) \
|
|
{ \
|
|
pitem = NULL; \
|
|
if (py_param) { \
|
|
if (PySecItem_Check(py_param)) { \
|
|
pitem = &((SecItem *)py_param)->item; \
|
|
} else if (none_ok && PyNone_Check(py_param)) { \
|
|
pitem = NULL; \
|
|
} else if (PyObject_CheckReadBuffer(py_param)) { \
|
|
unsigned char *data = NULL; \
|
|
Py_ssize_t data_len; \
|
|
\
|
|
if (PyObject_AsReadBuffer(py_param, (void *)&data, &data_len)) \
|
|
return -1; \
|
|
\
|
|
tmp_item.data = data; \
|
|
tmp_item.len = data_len; \
|
|
pitem = &tmp_item; \
|
|
} else { \
|
|
if (none_ok) { \
|
|
PyErr_SetString(PyExc_TypeError, param_name " must be SecItem, buffer compatible or None"); \
|
|
return -1; \
|
|
} else { \
|
|
PyErr_SetString(PyExc_TypeError, param_name " must be SecItem or buffer compatible"); \
|
|
return -1; \
|
|
} \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ========================= Formatting Utilities =========================== */
|
|
/* ========================================================================== */
|
|
|
|
|
|
typedef PyObject *(*format_lines_func)(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
static PyObject *
|
|
line_fmt_tuple(int level, const char *label, PyObject *py_value);
|
|
|
|
static PyObject *
|
|
make_line_fmt_tuples(int level, PyObject *src);
|
|
|
|
static PyObject *
|
|
py_make_line_fmt_tuples(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
static PyObject *
|
|
fmt_label(int level, char *label);
|
|
|
|
static PyObject *
|
|
format_from_lines(format_lines_func formatter, PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
static PyObject *
|
|
py_indented_format(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
#define FMT_OBJ_AND_APPEND(dst_fmt_tuples, label, src_obj, level, fail) \
|
|
{ \
|
|
PyObject *fmt_tuple = NULL; \
|
|
\
|
|
if ((fmt_tuple = line_fmt_tuple(level, label, src_obj)) == NULL) { \
|
|
goto fail; \
|
|
} \
|
|
if (PyList_Append(dst_fmt_tuples, fmt_tuple) != 0) { \
|
|
Py_DECREF(fmt_tuple); \
|
|
goto fail; \
|
|
} \
|
|
}
|
|
|
|
#define FMT_LABEL_AND_APPEND(dst_fmt_tuples, label, level, fail) \
|
|
{ \
|
|
PyObject *fmt_tuple = NULL; \
|
|
\
|
|
if ((fmt_tuple = fmt_label(level, label)) == NULL) { \
|
|
goto fail; \
|
|
} \
|
|
if (PyList_Append(dst_fmt_tuples, fmt_tuple) != 0) { \
|
|
Py_DECREF(fmt_tuple); \
|
|
goto fail; \
|
|
} \
|
|
}
|
|
|
|
#define APPEND_LINE_TUPLES_AND_CLEAR(dst_fmt_tuples, src_fmt_tuples, fail) \
|
|
{ \
|
|
PyObject *src_obj; \
|
|
Py_ssize_t len, i; \
|
|
if (src_fmt_tuples) { \
|
|
len = PyList_Size(src_fmt_tuples); \
|
|
for (i = 0; i < len; i++) { \
|
|
src_obj = PyList_GetItem(src_fmt_tuples, i); \
|
|
PyList_Append(dst_fmt_tuples, src_obj); \
|
|
} \
|
|
Py_CLEAR(src_fmt_tuples); \
|
|
} \
|
|
}
|
|
|
|
#define APPEND_LINES_AND_CLEAR(dst_fmt_tuples, src_lines, level, fail) \
|
|
{ \
|
|
PyObject *src_obj; \
|
|
Py_ssize_t len, i; \
|
|
if (src_lines) { \
|
|
len = PySequence_Size(src_lines); \
|
|
for (i = 0; i < len; i++) { \
|
|
src_obj = PySequence_GetItem(src_lines, i); \
|
|
FMT_OBJ_AND_APPEND(dst_fmt_tuples, NULL, src_obj, level, fail); \
|
|
Py_DECREF(src_obj); \
|
|
} \
|
|
Py_CLEAR(src_lines); \
|
|
} \
|
|
}
|
|
|
|
#define CALL_FORMAT_LINES_AND_APPEND(dst_fmt_tuples, obj, level, fail) \
|
|
{ \
|
|
PyObject *obj_line_fmt_tuples; \
|
|
\
|
|
if ((obj_line_fmt_tuples = \
|
|
PyObject_CallMethod(obj, "format_lines", \
|
|
"(i)", level)) == NULL) { \
|
|
goto fail; \
|
|
} \
|
|
\
|
|
APPEND_LINE_TUPLES_AND_CLEAR(dst_fmt_tuples, obj_line_fmt_tuples, fail); \
|
|
}
|
|
|
|
|
|
#define APPEND_OBJ_TO_HEX_LINES_AND_CLEAR(dst_fmt_tuples, obj, level, fail) \
|
|
{ \
|
|
PyObject *obj_lines; \
|
|
\
|
|
if ((obj_lines = obj_to_hex(obj, OCTETS_PER_LINE_DEFAULT, \
|
|
HEX_SEPARATOR_DEFAULT)) == NULL) { \
|
|
goto fail; \
|
|
} \
|
|
Py_CLEAR(obj); \
|
|
APPEND_LINES_AND_CLEAR(dst_fmt_tuples, obj_lines, level, fail); \
|
|
}
|
|
|
|
#define FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(dst_fmt_tuples, label, obj, level, fail) \
|
|
{ \
|
|
PyObject *obj_lines = NULL; \
|
|
SecItem *item = (SecItem *)obj; \
|
|
\
|
|
FMT_LABEL_AND_APPEND(dst_fmt_tuples, label, level, fail); \
|
|
if ((obj_lines = secitem_integer_format_lines(&item->item, level+1)) == NULL) { \
|
|
goto fail; \
|
|
} \
|
|
Py_CLEAR(obj); \
|
|
APPEND_LINE_TUPLES_AND_CLEAR(dst_fmt_tuples, obj_lines, fail); \
|
|
}
|
|
|
|
PyDoc_STRVAR(generic_format_doc,
|
|
"format(level=0, indent=' ') -> string)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
level : integer\n\
|
|
Initial indentation level, all subsequent indents are relative\n\
|
|
to this starting level.\n\
|
|
indent : string\n\
|
|
string replicated once for each indent level then prepended to output line\n\
|
|
\n\
|
|
This is equivalent to:\n\
|
|
indented_format(obj.format_lines()) on an object providing a format_lines() method.\n\
|
|
");
|
|
|
|
PyDoc_STRVAR(generic_format_lines_doc,
|
|
"format_lines(level=0) -> [(level, string),...]\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
level : integer\n\
|
|
Initial indentation level, all subsequent indents are relative\n\
|
|
to this starting level.\n\
|
|
\n\
|
|
Formats the object into a sequence of lines with indent level\n\
|
|
information. The return value is a list where each list item is a\n\
|
|
tuple. The first item in the tuple is an integer\n\
|
|
representing the indentation level for that line. Any remaining items\n\
|
|
in the tuple are strings to be output on that line.\n\
|
|
\n\
|
|
The output of this function can be formatted into a single string by\n\
|
|
calling `indented_format()`, e.g.:\n\
|
|
\n\
|
|
print indented_format(obj.format_lines())\n\
|
|
\n\
|
|
The reason this function returns a tuple as opposed to an single\n\
|
|
indented string is to support other text formatting systems such as\n\
|
|
GUI's with indentation controls. See `indented_format()` for a\n\
|
|
complete explanation.\n\
|
|
");
|
|
|
|
|
|
/* Steals reference to obj_str */
|
|
static PyObject *
|
|
line_fmt_tuple(int level, const char *label, PyObject *py_value)
|
|
{
|
|
Py_ssize_t tuple_size, i;
|
|
PyObject *fmt_tuple = NULL;
|
|
PyObject *py_label = NULL;
|
|
PyObject *py_value_str = NULL;
|
|
|
|
tuple_size = 1; /* always have level */
|
|
|
|
if (label) {
|
|
tuple_size++;
|
|
if ((py_label = PyString_FromFormat("%s:", label)) == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (py_value) {
|
|
tuple_size++;
|
|
if (PyString_Check(py_value) || PyUnicode_Check(py_value)) {
|
|
py_value_str = py_value;
|
|
Py_INCREF(py_value_str);
|
|
} else {
|
|
if ((py_value_str = PyObject_Str(py_value)) == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((fmt_tuple = PyTuple_New(tuple_size)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
i = 0;
|
|
PyTuple_SetItem(fmt_tuple, i++, PyInt_FromLong(level));
|
|
|
|
if (py_label) {
|
|
PyTuple_SetItem(fmt_tuple, i++, py_label);
|
|
}
|
|
|
|
if (py_value_str) {
|
|
PyTuple_SetItem(fmt_tuple, i++, py_value_str);
|
|
}
|
|
|
|
return fmt_tuple;
|
|
}
|
|
|
|
static PyObject *
|
|
make_line_fmt_tuples(int level, PyObject *src)
|
|
{
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *fmt_tuple = NULL;
|
|
PyObject *seq = NULL;
|
|
Py_ssize_t n_objs, i;
|
|
|
|
if (PyList_Check(src) || PyTuple_Check(src)) {
|
|
seq = src;
|
|
n_objs = PySequence_Size(seq);
|
|
Py_INCREF(seq);
|
|
} else {
|
|
obj = src;
|
|
Py_INCREF(obj);
|
|
n_objs = 1;
|
|
}
|
|
|
|
if ((lines = PyList_New(n_objs)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if (seq) {
|
|
for (i = 0; i < n_objs; i++) {
|
|
if ((obj = PySequence_GetItem(seq, i)) == NULL) { /* new reference */
|
|
Py_DECREF(lines);
|
|
goto exit;
|
|
}
|
|
if ((fmt_tuple = line_fmt_tuple(level, NULL, obj)) == NULL) {
|
|
Py_DECREF(lines);
|
|
goto exit;
|
|
}
|
|
PyList_SetItem(lines, i, fmt_tuple);
|
|
Py_CLEAR(obj);
|
|
}
|
|
} else {
|
|
if ((fmt_tuple = line_fmt_tuple(level, NULL, obj)) == NULL) {
|
|
Py_DECREF(lines);
|
|
goto exit;
|
|
}
|
|
PyList_SetItem(lines, 0, fmt_tuple);
|
|
}
|
|
|
|
exit:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(seq);
|
|
return lines;
|
|
}
|
|
|
|
PyDoc_STRVAR(py_make_line_fmt_tuples_doc,
|
|
"make_line_fmt_tuples(level, obj) -> [(level, str), ...]\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
obj : object\n\
|
|
If obj is a tuple or list then each member will be wrapped\n\
|
|
in a 2-tuple of (level, str). If obj is a scalar object\n\
|
|
then obj will be wrapped in a 2-tuple of (level, obj)\n\
|
|
level : integer\n\
|
|
Initial indentation level, all subsequent indents are relative\n\
|
|
to this starting level.\n\
|
|
\n\
|
|
Return a list of line formatted tuples sutible to passing to\n\
|
|
`indented_format()`. Each tuple consists of a integer\n\
|
|
level value and a string object. This is equivalent to:\n\
|
|
[(level, str(x)) for x in obj].\n\
|
|
As a special case convenience if obj is a scalar object (i.e.\n\
|
|
not a list or tuple) then [(level, str(obj))] will be returned.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
py_make_line_fmt_tuples(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", "obj", NULL};
|
|
int level = 0;
|
|
PyObject *obj;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "iO:make_line_fmt_tuples", kwlist,
|
|
&level, &obj))
|
|
return NULL;
|
|
|
|
return make_line_fmt_tuples(level, obj);
|
|
}
|
|
|
|
static PyObject *
|
|
fmt_label(int level, char *label)
|
|
{
|
|
return line_fmt_tuple(level, label, NULL);
|
|
}
|
|
|
|
static PyObject *
|
|
format_from_lines(format_lines_func formatter, PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", "indent_len", NULL};
|
|
int level = 0;
|
|
int indent_len = 4;
|
|
PyObject *py_lines = NULL;
|
|
PyObject *py_formatted_result = NULL;
|
|
PyObject *tmp_args = NULL;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:format", kwlist, &level, &indent_len))
|
|
return NULL;
|
|
|
|
if ((tmp_args = Py_BuildValue("(i)", level)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((py_lines = formatter(self, tmp_args, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(tmp_args);
|
|
|
|
if ((tmp_args = Py_BuildValue("Oi", py_lines, indent_len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((py_formatted_result = py_indented_format(NULL, tmp_args, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
Py_DECREF(tmp_args);
|
|
Py_DECREF(py_lines);
|
|
return py_formatted_result;
|
|
|
|
fail:
|
|
Py_XDECREF(tmp_args);
|
|
Py_XDECREF(py_lines);
|
|
return NULL;
|
|
}
|
|
|
|
PyDoc_STRVAR(py_indented_format_doc,
|
|
"indented_format(line_fmt_tuples, indent_len=4) -> string\n\
|
|
\n\
|
|
The function supports the display of complex objects which may be\n\
|
|
composed of other complex objects. There is often a need to output\n\
|
|
section headers or single strings and lists of <attribute,value> pairs\n\
|
|
(the attribute in this discussion is called a label), or even blank\n\
|
|
lines. All of these items should line up in columns at different\n\
|
|
indentation levels in order to visually see the structure.\n\
|
|
\n\
|
|
It would not be flexible enough to have object formatting routines\n\
|
|
which simply returned a single string with all the indentation and\n\
|
|
formatting pre-applied. The indentation width may not be what is\n\
|
|
desired. Or more importantly you might not be outputting to text\n\
|
|
display. It might be a GUI which desires to display the\n\
|
|
information. Most GUI's want to handle each string seperately and\n\
|
|
control indentation and the visibility of each item (e.g. a tree\n\
|
|
control).\n\
|
|
\n\
|
|
At the same time we want to satisfy the need for easy and simple text\n\
|
|
output. This routine will do that, e.g.:\n\
|
|
\n\
|
|
print indented_format(obj.format_lines())\n\
|
|
\n\
|
|
To accomodate necessary flexibility the object formatting methods\n\
|
|
(format_lines()) return a list of tuples. Each tuple represents a\n\
|
|
single line with the first tuple item being the indentation level for\n\
|
|
the line. There may be 0,1 or 2 additional strings in the tuple which\n\
|
|
are to be output on the line. A single string are usually one of two\n\
|
|
things, either a section header or data that has been continuted onto\n\
|
|
multiple lines. Two strings usually represent a <attribute,value> pair\n\
|
|
with the first string being a label (e.g. attribute name).\n\
|
|
\n\
|
|
Each tuple may be:\n\
|
|
\n\
|
|
(int,)\n\
|
|
1-value tuple, no strings, e.g. blank line.\n\
|
|
\n\
|
|
(int, string)\n\
|
|
2-value tuple, output string at indent level.\n\
|
|
\n\
|
|
(int, string, string)\n\
|
|
3-value tuple, first string is a label, second string is a\n\
|
|
value. Starting at the indent level output the label, then\n\
|
|
follow with the value. By keeping the label separate from the\n\
|
|
value the ouput formatter may elect to align the values in\n\
|
|
vertical columns for adjacent lines.\n\
|
|
\n\
|
|
Example::\n \
|
|
\n\
|
|
# This list of tuples,\n\
|
|
\n\
|
|
[(0, 'Constraints'),\n\
|
|
(1, 'min:', '0')\n\
|
|
(1, 'max:', '100'),\n\
|
|
(1, 'Filter Data'),\n\
|
|
(2, 'ab bc de f0 12 34 56 78 9a bc de f0')\n\
|
|
(2, '12 34 56 78 9a bc de f0 12 34 56 78')\n\
|
|
]\n\
|
|
\n\
|
|
# would product this output\n\
|
|
\n\
|
|
Constraints\n\
|
|
min: 0\n\
|
|
max: 100\n\
|
|
Filter Data:\n\
|
|
ab bc de f0 12 34 56 78 9a bc de f0\n\
|
|
12 34 56 78 9a bc de f0 12 34 56 78\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
line_fmt_tuples : [(level, ...),...]\n\
|
|
A list of tuples. First tuple value is the indentation level\n\
|
|
followed by optional strings for the line.\n\
|
|
indent_len : int\n\
|
|
Number of space characters repeated for each level and\n\
|
|
prepended to the line string.\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
py_indented_format(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
typedef struct {
|
|
Py_ssize_t indent_len;
|
|
Py_ssize_t label_len;
|
|
Py_ssize_t value_len;
|
|
Py_ssize_t justification_len;
|
|
} LineInfo;
|
|
|
|
|
|
static char *kwlist[] = {"lines_pairs", "indent_len", NULL};
|
|
PyObject *py_lines = NULL;
|
|
long line_level = 0;
|
|
int indent_len = 4;
|
|
int cur_indent_len = 0;
|
|
char *src=NULL, *dst=NULL;
|
|
Py_ssize_t num_lines, tuple_len;
|
|
char *label = NULL;
|
|
char *value = NULL;
|
|
Py_ssize_t label_len, value_len, justification_len, max_align;
|
|
char *src_end = NULL;
|
|
PyObject *py_line_fmt_tuple = NULL;
|
|
PyObject *py_level = NULL;
|
|
PyObject *py_label = NULL;
|
|
PyObject *py_value = NULL;
|
|
PyObject *py_string_utf8 = NULL;
|
|
Py_ssize_t cur_formatted_line_len;
|
|
PyObject *py_formatted_str = NULL;
|
|
Py_ssize_t formatted_str_len;
|
|
char *formatted_str;
|
|
Py_ssize_t i, j, k;
|
|
LineInfo *line_info = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|i:indented_format", kwlist,
|
|
&PyList_Type, &py_lines, &indent_len))
|
|
return NULL;
|
|
|
|
num_lines = PyList_Size(py_lines);
|
|
|
|
/*
|
|
* Because we interrogate the length of the various strings
|
|
* multiple times in the various loops we don't want to repeatedly
|
|
* dereference and query the Pyton objects each time. So we
|
|
* allocate an array to cache the information for efficency
|
|
* purposes.
|
|
*/
|
|
|
|
if ((line_info = PyMem_Malloc(num_lines*sizeof(LineInfo))) == NULL) {
|
|
return PyErr_NoMemory();
|
|
}
|
|
|
|
/*
|
|
* Step 1: Scan all the lines and get the string sizes. Do all
|
|
* error checking in this loop so we don't have to do it again
|
|
* later. Cache the size information for faster access in
|
|
* subseqent loops.
|
|
*/
|
|
|
|
for (i = 0; i < num_lines; i++) {
|
|
py_label = NULL;
|
|
label = NULL;
|
|
label_len = 0;
|
|
|
|
py_value = NULL;
|
|
value = NULL;
|
|
value_len = 0;
|
|
|
|
py_line_fmt_tuple = PyList_GetItem(py_lines, i);
|
|
if (!PyTuple_Check(py_line_fmt_tuple)) {
|
|
PyErr_Format(PyExc_TypeError, "line_fmt_tuples[%zd] must be a tuple, not %.200s",
|
|
i, Py_TYPE(py_line_fmt_tuple)->tp_name);
|
|
goto fail;
|
|
}
|
|
|
|
tuple_len = PyTuple_Size(py_line_fmt_tuple);
|
|
|
|
if (tuple_len < 1 || tuple_len > 3) {
|
|
PyErr_Format(PyExc_TypeError, "line_fmt_tuples[%zd] tuple must have 1-3 items, not %d items",
|
|
i, tuple_len);
|
|
goto fail;
|
|
}
|
|
|
|
py_level = PyTuple_GetItem(py_line_fmt_tuple, 0);
|
|
if (tuple_len == 2) {
|
|
py_label = PyTuple_GetItem(py_line_fmt_tuple, 1);
|
|
} else if (tuple_len == 3) {
|
|
py_label = PyTuple_GetItem(py_line_fmt_tuple, 1);
|
|
py_value = PyTuple_GetItem(py_line_fmt_tuple, 2);
|
|
}
|
|
|
|
if (!PyInt_Check(py_level)) {
|
|
PyErr_Format(PyExc_TypeError, "item[0] in the tuple at line_fmt_tuples[%zd] list must be an integer, not %.200s",
|
|
i, Py_TYPE(py_level)->tp_name);
|
|
goto fail;
|
|
}
|
|
line_level = PyInt_AsLong(py_level);
|
|
if (line_level < 0) {
|
|
PyErr_Format(PyExc_TypeError, "item[0] in the tuple at line_fmt_tuples[%zd] list must be a non-negative integer, not %ld",
|
|
i, line_level);
|
|
goto fail;
|
|
}
|
|
|
|
label_len = value_len = 0;
|
|
if (py_label) {
|
|
if ((py_string_utf8 = PyString_UTF8(py_label, "label")) == NULL) {
|
|
PyErr_Format(PyExc_TypeError, "item[1] in the tuple at line_fmt_tuples[%zd] list must be a string, not %.200s",
|
|
i, Py_TYPE(py_label)->tp_name);
|
|
goto fail;
|
|
}
|
|
if (PyString_AsStringAndSize(py_string_utf8, &label, &label_len) == -1) {
|
|
goto fail;
|
|
}
|
|
}
|
|
Py_CLEAR(py_string_utf8);
|
|
|
|
if (py_value) {
|
|
if ((py_string_utf8 = PyString_UTF8(py_value, "value")) == NULL) {
|
|
PyErr_Format(PyExc_TypeError, "item[2] in the tuple at line_fmt_tuples[%zd] list must be a string, not %.200s",
|
|
i, Py_TYPE(py_value)->tp_name);
|
|
goto fail;
|
|
}
|
|
if (PyString_AsStringAndSize(py_string_utf8, &value, &value_len) == -1) {
|
|
goto fail;
|
|
}
|
|
}
|
|
Py_CLEAR(py_string_utf8);
|
|
|
|
/* Cache the length information */
|
|
line_info[i].label_len = label_len;
|
|
line_info[i].value_len = value_len;
|
|
line_info[i].justification_len = 0;
|
|
line_info[i].indent_len = line_level * indent_len;
|
|
}
|
|
|
|
/*
|
|
* Step 2: Locate labels and values that appear on consecutive
|
|
* lines at the same indentation level. Compute the alignment for
|
|
* values such that values all line up in the same column.
|
|
*
|
|
* We consider only lines that have both a label and a value for
|
|
* the purpose of computing the alignment, if a line has only a
|
|
* label we ignore it when establishing value alignment.
|
|
*
|
|
* A change in the indendation level resets the alignment.
|
|
*/
|
|
for (i = 0; i < num_lines;) {
|
|
cur_indent_len = line_info[i].indent_len;
|
|
if (line_info[i].value_len) {
|
|
max_align = line_info[i].label_len;
|
|
} else {
|
|
max_align = 0;
|
|
}
|
|
|
|
/*
|
|
* Search forward for consecutive lines that share the same
|
|
* indendation level. If the line has value then use it's
|
|
* label to compute the maximum width of all labels in this
|
|
* group of lines.
|
|
*/
|
|
for (j = i+1; j < num_lines && cur_indent_len == line_info[j].indent_len; j++) {
|
|
if (line_info[j].value_len) {
|
|
if (line_info[j].label_len > max_align) {
|
|
max_align = line_info[j].label_len;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now we know the maximum width of all labels in this group
|
|
* of lines. We always provide 1 space between a label and
|
|
* it's value so we add 1 to the maximum label width, this
|
|
* becomes our column for value alignment.
|
|
*
|
|
* If there were no values in this group of lines max_align
|
|
* will be zero and we won't be doing any value alignment.
|
|
*/
|
|
if (max_align) {
|
|
max_align += 1;
|
|
}
|
|
|
|
/*
|
|
* Now that we know the alignment column go back and compute
|
|
* how much space to add at the end of each label to hit the
|
|
* alignment column when we append the value.
|
|
*/
|
|
for (k = i; k < j; k++) {
|
|
if (line_info[k].value_len) { /* Only justify if there is a value */
|
|
line_info[k].justification_len = max_align - line_info[k].label_len;
|
|
}
|
|
}
|
|
|
|
/* This group of lines is processed, advance to the next group. */
|
|
i = j;
|
|
}
|
|
|
|
/*
|
|
* Step 3: We now know how many characters every line consumes,
|
|
* compute the total buffer size required and allocate it.
|
|
*/
|
|
formatted_str_len = 0;
|
|
for (i = 0; i < num_lines; i++) {
|
|
cur_formatted_line_len = line_info[i].indent_len +
|
|
line_info[i].label_len +
|
|
line_info[i].justification_len +
|
|
line_info[i].value_len + 1; /* +1 for newline */
|
|
formatted_str_len += cur_formatted_line_len;
|
|
}
|
|
|
|
if (num_lines > 0) formatted_str_len -= 1; /* last line doesn't get a new line appended */
|
|
if ((py_formatted_str = PyString_FromStringAndSize(NULL, formatted_str_len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
formatted_str = PyString_AsString(py_formatted_str);
|
|
dst = formatted_str;
|
|
|
|
/*
|
|
* Step 4: For each line: Insert the indent. If it has a label
|
|
* insert the label. If it has a value insert the justification to
|
|
* align the values, then insert the value. Finally append a
|
|
* newline (except for the last line).
|
|
*/
|
|
for (i = 0; i < num_lines; i++) {
|
|
py_label = NULL;
|
|
label = NULL;
|
|
|
|
py_value = NULL;
|
|
value = NULL;
|
|
|
|
py_line_fmt_tuple = PyList_GetItem(py_lines, i);
|
|
|
|
cur_indent_len = line_info[i].indent_len;
|
|
label_len = line_info[i].label_len;
|
|
value_len = line_info[i].value_len;
|
|
justification_len = line_info[i].justification_len;
|
|
|
|
/* Insert the indent */
|
|
for (j = 0; j < cur_indent_len; j++) *dst++ = ' ';
|
|
|
|
/* Insert the label */
|
|
if (label_len) {
|
|
py_label = PyTuple_GetItem(py_line_fmt_tuple, 1);
|
|
py_string_utf8 = PyString_UTF8(py_label, "label");
|
|
label = PyString_AsString(py_string_utf8);
|
|
|
|
for (src = label, src_end = label + label_len; src < src_end; *dst++ = *src++);
|
|
|
|
Py_CLEAR(py_string_utf8);
|
|
}
|
|
|
|
/* Insert the alignment justification for the value */
|
|
for (j = 0; j < justification_len; j++) *dst++ = ' ';
|
|
|
|
/* Insert the value */
|
|
if (value_len) {
|
|
py_value = PyTuple_GetItem(py_line_fmt_tuple, 2);
|
|
py_string_utf8 = PyString_UTF8(py_value, "value");
|
|
value = PyString_AsString(py_string_utf8);
|
|
|
|
for (src = value, src_end = value + value_len; src < src_end; *dst++ = *src++);
|
|
|
|
Py_CLEAR(py_string_utf8);
|
|
}
|
|
|
|
/* Add a new line, except for the last line */
|
|
if (i < num_lines-1)
|
|
*dst++ = '\n';
|
|
}
|
|
|
|
/*
|
|
* Done. Sanity check we've written exactly the buffer we allocated.
|
|
*/
|
|
assert(formatted_str + PyString_Size(py_formatted_str) == dst);
|
|
return py_formatted_str;
|
|
|
|
fail:
|
|
Py_CLEAR(py_string_utf8);
|
|
PyMem_Free(line_info);
|
|
Py_XDECREF(py_formatted_str);
|
|
return NULL;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
|
|
/* Copied from mozilla/security/nss/lib/certdb/alg1485.c */
|
|
typedef struct DnAvaPropsStr {
|
|
const char * name;
|
|
unsigned int maxLen; /* max bytes in UTF8 encoded string value */
|
|
SECOidTag oid_tag;
|
|
int value_type;
|
|
} DnAvaProps;
|
|
|
|
static const DnAvaProps dn_ava_props[] = {
|
|
/* IANA registered type names
|
|
* (See: http://www.iana.org/assignments/ldap-parameters)
|
|
*/
|
|
/* RFC 3280, 4630 MUST SUPPORT */
|
|
{ "CN", 64, SEC_OID_AVA_COMMON_NAME, SEC_ASN1_UTF8_STRING},
|
|
{ "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE,
|
|
SEC_ASN1_UTF8_STRING},
|
|
{ "O", 64, SEC_OID_AVA_ORGANIZATION_NAME,
|
|
SEC_ASN1_UTF8_STRING},
|
|
{ "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
|
|
SEC_ASN1_UTF8_STRING},
|
|
{ "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER, SEC_ASN1_PRINTABLE_STRING},
|
|
{ "C", 2, SEC_OID_AVA_COUNTRY_NAME, SEC_ASN1_PRINTABLE_STRING},
|
|
{ "serialNumber", 64, SEC_OID_AVA_SERIAL_NUMBER,SEC_ASN1_PRINTABLE_STRING},
|
|
|
|
/* RFC 3280, 4630 SHOULD SUPPORT */
|
|
{ "L", 128, SEC_OID_AVA_LOCALITY, SEC_ASN1_UTF8_STRING},
|
|
{ "title", 64, SEC_OID_AVA_TITLE, SEC_ASN1_UTF8_STRING},
|
|
{ "SN", 64, SEC_OID_AVA_SURNAME, SEC_ASN1_UTF8_STRING},
|
|
{ "givenName", 64, SEC_OID_AVA_GIVEN_NAME, SEC_ASN1_UTF8_STRING},
|
|
{ "initials", 64, SEC_OID_AVA_INITIALS, SEC_ASN1_UTF8_STRING},
|
|
{ "generationQualifier",
|
|
64, SEC_OID_AVA_GENERATION_QUALIFIER,
|
|
SEC_ASN1_UTF8_STRING},
|
|
/* RFC 3280, 4630 MAY SUPPORT */
|
|
{ "DC", 128, SEC_OID_AVA_DC, SEC_ASN1_IA5_STRING},
|
|
{ "MAIL", 256, SEC_OID_RFC1274_MAIL, SEC_ASN1_IA5_STRING},
|
|
{ "UID", 256, SEC_OID_RFC1274_UID, SEC_ASN1_UTF8_STRING},
|
|
|
|
/* values from draft-ietf-ldapbis-user-schema-05 (not in RFC 3280) */
|
|
{ "postalAddress", 128, SEC_OID_AVA_POSTAL_ADDRESS, SEC_ASN1_UTF8_STRING},
|
|
{ "postalCode", 40, SEC_OID_AVA_POSTAL_CODE, SEC_ASN1_UTF8_STRING},
|
|
{ "postOfficeBox", 40, SEC_OID_AVA_POST_OFFICE_BOX,SEC_ASN1_UTF8_STRING},
|
|
{ "houseIdentifier",64, SEC_OID_AVA_HOUSE_IDENTIFIER,SEC_ASN1_UTF8_STRING},
|
|
/* end of IANA registered type names */
|
|
|
|
/* legacy keywords */
|
|
{ "E", 128, SEC_OID_PKCS9_EMAIL_ADDRESS,SEC_ASN1_IA5_STRING},
|
|
|
|
#if 0 /* removed. Not yet in any IETF draft or RFC. */
|
|
{ "pseudonym", 64, SEC_OID_AVA_PSEUDONYM, SEC_ASN1_UTF8_STRING},
|
|
#endif
|
|
|
|
{ 0, 256, SEC_OID_UNKNOWN , 0},
|
|
};
|
|
|
|
/* ========================================================================== */
|
|
typedef struct {
|
|
unsigned short len;
|
|
char *encoded;
|
|
} AsciiEscapes;
|
|
|
|
static AsciiEscapes ascii_encoding_table[256] = {
|
|
{4, "\\x00"}, /* 0 */ {4, "\\x01"}, /* 1 */
|
|
{4, "\\x02"}, /* 2 */ {4, "\\x03"}, /* 3 */
|
|
{4, "\\x04"}, /* 4 */ {4, "\\x05"}, /* 5 */
|
|
{4, "\\x06"}, /* 6 */ {2, "\\a" }, /* 7 BELL */
|
|
{2, "\\b" }, /* 8 BS */ {2, "\\t" }, /* 9 HTAB */
|
|
{2, "\\n" }, /* 10 NL */ {2, "\\v" }, /* 11 VTAB */
|
|
{2, "\\f" }, /* 12 FF */ {2, "\\r" }, /* 13 CR */
|
|
{4, "\\x0E"}, /* 14 */ {4, "\\x0F"}, /* 15 */
|
|
{4, "\\x10"}, /* 16 */ {4, "\\x11"}, /* 17 */
|
|
{4, "\\x12"}, /* 18 */ {4, "\\x13"}, /* 19 */
|
|
{4, "\\x14"}, /* 20 */ {4, "\\x15"}, /* 21 */
|
|
{4, "\\x16"}, /* 22 */ {4, "\\x17"}, /* 23 */
|
|
{4, "\\x18"}, /* 24 */ {4, "\\x19"}, /* 25 */
|
|
{4, "\\x1A"}, /* 26 */ {4, "\\x1B"}, /* 27 */
|
|
{4, "\\x1C"}, /* 28 */ {4, "\\x1D"}, /* 29 */
|
|
{4, "\\x1E"}, /* 30 */ {4, "\\x1F"}, /* 31 */
|
|
{1, " " }, /* 32 */ {1, "!" }, /* 33 ! */
|
|
{2, "\\\"" }, /* 34 " */ {1, "#" }, /* 35 # */
|
|
{1, "$" }, /* 36 $ */ {1, "%" }, /* 37 % */
|
|
{1, "&" }, /* 38 & */ {2, "\\'" }, /* 39 ' */
|
|
{1, "(" }, /* 40 ( */ {1, ")" }, /* 41 ) */
|
|
{1, "*" }, /* 42 * */ {1, "+" }, /* 43 + */
|
|
{1, "," }, /* 44 , */ {1, "-" }, /* 45 - */
|
|
{1, "." }, /* 46 . */ {1, "/" }, /* 47 / */
|
|
{1, "0" }, /* 48 0 */ {1, "1" }, /* 49 1 */
|
|
{1, "2" }, /* 50 2 */ {1, "3" }, /* 51 3 */
|
|
{1, "4" }, /* 52 4 */ {1, "5" }, /* 53 5 */
|
|
{1, "6" }, /* 54 6 */ {1, "7" }, /* 55 7 */
|
|
{1, "8" }, /* 56 8 */ {1, "9" }, /* 57 9 */
|
|
{1, ":" }, /* 58 : */ {1, ";" }, /* 59 ; */
|
|
{1, "<" }, /* 60 < */ {1, "=" }, /* 61 = */
|
|
{1, ">" }, /* 62 > */ {2, "\\?" }, /* 63 ? */
|
|
{1, "@" }, /* 64 @ */ {1, "A" }, /* 65 A */
|
|
{1, "B" }, /* 66 B */ {1, "C" }, /* 67 C */
|
|
{1, "D" }, /* 68 D */ {1, "E" }, /* 69 E */
|
|
{1, "F" }, /* 70 F */ {1, "G" }, /* 71 G */
|
|
{1, "H" }, /* 72 H */ {1, "I" }, /* 73 I */
|
|
{1, "J" }, /* 74 J */ {1, "K" }, /* 75 K */
|
|
{1, "L" }, /* 76 L */ {1, "M" }, /* 77 M */
|
|
{1, "N" }, /* 78 N */ {1, "O" }, /* 79 O */
|
|
{1, "P" }, /* 80 P */ {1, "Q" }, /* 81 Q */
|
|
{1, "R" }, /* 82 R */ {1, "S" }, /* 83 S */
|
|
{1, "T" }, /* 84 T */ {1, "U" }, /* 85 U */
|
|
{1, "V" }, /* 86 V */ {1, "W" }, /* 87 W */
|
|
{1, "X" }, /* 88 X */ {1, "Y" }, /* 89 Y */
|
|
{1, "Z" }, /* 90 Z */ {1, "[" }, /* 91 [ */
|
|
{2, "\\\\" }, /* 92 \ */ {1, "]" }, /* 93 ] */
|
|
{1, "^" }, /* 94 ^ */ {1, "_" }, /* 95 _ */
|
|
{1, "`" }, /* 96 ` */ {1, "a" }, /* 97 a */
|
|
{1, "b" }, /* 98 b */ {1, "c" }, /* 99 c */
|
|
{1, "d" }, /* 100 d */ {1, "e" }, /* 101 e */
|
|
{1, "f" }, /* 102 f */ {1, "g" }, /* 103 g */
|
|
{1, "h" }, /* 104 h */ {1, "i" }, /* 105 i */
|
|
{1, "j" }, /* 106 j */ {1, "k" }, /* 107 k */
|
|
{1, "l" }, /* 108 l */ {1, "m" }, /* 109 m */
|
|
{1, "n" }, /* 110 n */ {1, "o" }, /* 111 o */
|
|
{1, "p" }, /* 112 p */ {1, "q" }, /* 113 q */
|
|
{1, "r" }, /* 114 r */ {1, "s" }, /* 115 s */
|
|
{1, "t" }, /* 116 t */ {1, "u" }, /* 117 u */
|
|
{1, "v" }, /* 118 v */ {1, "w" }, /* 119 w */
|
|
{1, "x" }, /* 120 x */ {1, "y" }, /* 121 y */
|
|
{1, "z" }, /* 122 z */ {1, "{" }, /* 123 { */
|
|
{1, "|" }, /* 124 | */ {1, "}" }, /* 125 } */
|
|
{1, "~" }, /* 126 ~ */ {4, "\\x7F"}, /* 127 */
|
|
{4, "\\x80"}, /* 128 */ {4, "\\x81"}, /* 129 */
|
|
{4, "\\x82"}, /* 130 */ {4, "\\x83"}, /* 131 */
|
|
{4, "\\x84"}, /* 132 */ {4, "\\x85"}, /* 133 */
|
|
{4, "\\x86"}, /* 134 */ {4, "\\x87"}, /* 135 */
|
|
{4, "\\x88"}, /* 136 */ {4, "\\x89"}, /* 137 */
|
|
{4, "\\x8A"}, /* 138 */ {4, "\\x8B"}, /* 139 */
|
|
{4, "\\x8C"}, /* 140 */ {4, "\\x8D"}, /* 141 */
|
|
{4, "\\x8E"}, /* 142 */ {4, "\\x8F"}, /* 143 */
|
|
{4, "\\x90"}, /* 144 */ {4, "\\x91"}, /* 145 */
|
|
{4, "\\x92"}, /* 146 */ {4, "\\x93"}, /* 147 */
|
|
{4, "\\x94"}, /* 148 */ {4, "\\x95"}, /* 149 */
|
|
{4, "\\x96"}, /* 150 */ {4, "\\x97"}, /* 151 */
|
|
{4, "\\x98"}, /* 152 */ {4, "\\x99"}, /* 153 */
|
|
{4, "\\x9A"}, /* 154 */ {4, "\\x9B"}, /* 155 */
|
|
{4, "\\x9C"}, /* 156 */ {4, "\\x9D"}, /* 157 */
|
|
{4, "\\x9E"}, /* 158 */ {4, "\\x9F"}, /* 159 */
|
|
{4, "\\xA0"}, /* 160 */ {4, "\\xA1"}, /* 161 */
|
|
{4, "\\xA2"}, /* 162 */ {4, "\\xA3"}, /* 163 */
|
|
{4, "\\xA4"}, /* 164 */ {4, "\\xA5"}, /* 165 */
|
|
{4, "\\xA6"}, /* 166 */ {4, "\\xA7"}, /* 167 */
|
|
{4, "\\xA8"}, /* 168 */ {4, "\\xA9"}, /* 169 */
|
|
{4, "\\xAA"}, /* 170 */ {4, "\\xAB"}, /* 171 */
|
|
{4, "\\xAC"}, /* 172 */ {4, "\\xAD"}, /* 173 */
|
|
{4, "\\xAE"}, /* 174 */ {4, "\\xAF"}, /* 175 */
|
|
{4, "\\xB0"}, /* 176 */ {4, "\\xB1"}, /* 177 */
|
|
{4, "\\xB2"}, /* 178 */ {4, "\\xB3"}, /* 179 */
|
|
{4, "\\xB4"}, /* 180 */ {4, "\\xB5"}, /* 181 */
|
|
{4, "\\xB6"}, /* 182 */ {4, "\\xB7"}, /* 183 */
|
|
{4, "\\xB8"}, /* 184 */ {4, "\\xB9"}, /* 185 */
|
|
{4, "\\xBA"}, /* 186 */ {4, "\\xBB"}, /* 187 */
|
|
{4, "\\xBC"}, /* 188 */ {4, "\\xBD"}, /* 189 */
|
|
{4, "\\xBE"}, /* 190 */ {4, "\\xBF"}, /* 191 */
|
|
{4, "\\xC0"}, /* 192 */ {4, "\\xC1"}, /* 193 */
|
|
{4, "\\xC2"}, /* 194 */ {4, "\\xC3"}, /* 195 */
|
|
{4, "\\xC4"}, /* 196 */ {4, "\\xC5"}, /* 197 */
|
|
{4, "\\xC6"}, /* 198 */ {4, "\\xC7"}, /* 199 */
|
|
{4, "\\xC8"}, /* 200 */ {4, "\\xC9"}, /* 201 */
|
|
{4, "\\xCA"}, /* 202 */ {4, "\\xCB"}, /* 203 */
|
|
{4, "\\xCC"}, /* 204 */ {4, "\\xCD"}, /* 205 */
|
|
{4, "\\xCE"}, /* 206 */ {4, "\\xCF"}, /* 207 */
|
|
{4, "\\xD0"}, /* 208 */ {4, "\\xD1"}, /* 209 */
|
|
{4, "\\xD2"}, /* 210 */ {4, "\\xD3"}, /* 211 */
|
|
{4, "\\xD4"}, /* 212 */ {4, "\\xD5"}, /* 213 */
|
|
{4, "\\xD6"}, /* 214 */ {4, "\\xD7"}, /* 215 */
|
|
{4, "\\xD8"}, /* 216 */ {4, "\\xD9"}, /* 217 */
|
|
{4, "\\xDA"}, /* 218 */ {4, "\\xDB"}, /* 219 */
|
|
{4, "\\xDC"}, /* 220 */ {4, "\\xDD"}, /* 221 */
|
|
{4, "\\xDE"}, /* 222 */ {4, "\\xDF"}, /* 223 */
|
|
{4, "\\xE0"}, /* 224 */ {4, "\\xE1"}, /* 225 */
|
|
{4, "\\xE2"}, /* 226 */ {4, "\\xE3"}, /* 227 */
|
|
{4, "\\xE4"}, /* 228 */ {4, "\\xE5"}, /* 229 */
|
|
{4, "\\xE6"}, /* 230 */ {4, "\\xE7"}, /* 231 */
|
|
{4, "\\xE8"}, /* 232 */ {4, "\\xE9"}, /* 233 */
|
|
{4, "\\xEA"}, /* 234 */ {4, "\\xEB"}, /* 235 */
|
|
{4, "\\xEC"}, /* 236 */ {4, "\\xED"}, /* 237 */
|
|
{4, "\\xEE"}, /* 238 */ {4, "\\xEF"}, /* 239 */
|
|
{4, "\\xF0"}, /* 240 */ {4, "\\xF1"}, /* 241 */
|
|
{4, "\\xF2"}, /* 242 */ {4, "\\xF3"}, /* 243 */
|
|
{4, "\\xF4"}, /* 244 */ {4, "\\xF5"}, /* 245 */
|
|
{4, "\\xF6"}, /* 246 */ {4, "\\xF7"}, /* 247 */
|
|
{4, "\\xF8"}, /* 248 */ {4, "\\xF9"}, /* 249 */
|
|
{4, "\\xFA"}, /* 250 */ {4, "\\xFB"}, /* 251 */
|
|
{4, "\\xFC"}, /* 252 */ {4, "\\xFD"}, /* 253 */
|
|
{4, "\\xFE"}, /* 254 */ {4, "\\xFF"}, /* 255 */
|
|
};
|
|
|
|
/* From nss/cmd/certutil/keystuff.c */
|
|
static const unsigned char P[] = { 0,
|
|
0x98, 0xef, 0x3a, 0xae, 0x70, 0x98, 0x9b, 0x44,
|
|
0xdb, 0x35, 0x86, 0xc1, 0xb6, 0xc2, 0x47, 0x7c,
|
|
0xb4, 0xff, 0x99, 0xe8, 0xae, 0x44, 0xf2, 0xeb,
|
|
0xc3, 0xbe, 0x23, 0x0f, 0x65, 0xd0, 0x4c, 0x04,
|
|
0x82, 0x90, 0xa7, 0x9d, 0x4a, 0xc8, 0x93, 0x7f,
|
|
0x41, 0xdf, 0xf8, 0x80, 0x6b, 0x0b, 0x68, 0x7f,
|
|
0xaf, 0xe4, 0xa8, 0xb5, 0xb2, 0x99, 0xc3, 0x69,
|
|
0xfb, 0x3f, 0xe7, 0x1b, 0xd0, 0x0f, 0xa9, 0x7a,
|
|
0x4a, 0x04, 0xbf, 0x50, 0x9e, 0x22, 0x33, 0xb8,
|
|
0x89, 0x53, 0x24, 0x10, 0xf9, 0x68, 0x77, 0xad,
|
|
0xaf, 0x10, 0x68, 0xb8, 0xd3, 0x68, 0x5d, 0xa3,
|
|
0xc3, 0xeb, 0x72, 0x3b, 0xa0, 0x0b, 0x73, 0x65,
|
|
0xc5, 0xd1, 0xfa, 0x8c, 0xc0, 0x7d, 0xaa, 0x52,
|
|
0x29, 0x34, 0x44, 0x01, 0xbf, 0x12, 0x25, 0xfe,
|
|
0x18, 0x0a, 0xc8, 0x3f, 0xc1, 0x60, 0x48, 0xdb,
|
|
0xad, 0x93, 0xb6, 0x61, 0x67, 0xd7, 0xa8, 0x2d };
|
|
static const unsigned char Q[] = { 0,
|
|
0xb5, 0xb0, 0x84, 0x8b, 0x44, 0x29, 0xf6, 0x33,
|
|
0x59, 0xa1, 0x3c, 0xbe, 0xd2, 0x7f, 0x35, 0xa1,
|
|
0x76, 0x27, 0x03, 0x81 };
|
|
static const unsigned char G[] = {
|
|
0x04, 0x0e, 0x83, 0x69, 0xf1, 0xcd, 0x7d, 0xe5,
|
|
0x0c, 0x78, 0x93, 0xd6, 0x49, 0x6f, 0x00, 0x04,
|
|
0x4e, 0x0e, 0x6c, 0x37, 0xaa, 0x38, 0x22, 0x47,
|
|
0xd2, 0x58, 0xec, 0x83, 0x12, 0x95, 0xf9, 0x9c,
|
|
0xf1, 0xf4, 0x27, 0xff, 0xd7, 0x99, 0x57, 0x35,
|
|
0xc6, 0x64, 0x4c, 0xc0, 0x47, 0x12, 0x31, 0x50,
|
|
0x82, 0x3c, 0x2a, 0x07, 0x03, 0x01, 0xef, 0x30,
|
|
0x09, 0x89, 0x82, 0x41, 0x76, 0x71, 0xda, 0x9e,
|
|
0x57, 0x8b, 0x76, 0x38, 0x37, 0x5f, 0xa5, 0xcd,
|
|
0x32, 0x84, 0x45, 0x8d, 0x4c, 0x17, 0x54, 0x2b,
|
|
0x5d, 0xc2, 0x6b, 0xba, 0x3e, 0xa0, 0x7b, 0x95,
|
|
0xd7, 0x00, 0x42, 0xf7, 0x08, 0xb8, 0x83, 0x87,
|
|
0x60, 0xe1, 0xe5, 0xf4, 0x1a, 0x54, 0xc2, 0x20,
|
|
0xda, 0x38, 0x3a, 0xd1, 0xb6, 0x10, 0xf4, 0xcb,
|
|
0x35, 0xda, 0x97, 0x92, 0x87, 0xd6, 0xa5, 0x37,
|
|
0x62, 0xb4, 0x93, 0x4a, 0x15, 0x21, 0xa5, 0x10 };
|
|
|
|
static const SECKEYPQGParams default_pqg_params = {
|
|
NULL,
|
|
{ 0, (unsigned char *)P, sizeof(P) },
|
|
{ 0, (unsigned char *)Q, sizeof(Q) },
|
|
{ 0, (unsigned char *)G, sizeof(G) }
|
|
};
|
|
|
|
/*
|
|
* Returns the number of bytes needed to escape an ascii string.
|
|
*/
|
|
static size_t
|
|
ascii_encoded_strnlen(const char *str, size_t len)
|
|
{
|
|
size_t result;
|
|
const unsigned char *s; /* must be unsigned for table indexing to work */
|
|
|
|
for (s = (unsigned char *)str, result = 0; len; s++, len--) {
|
|
result += ascii_encoding_table[*s].len;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
static char time_format[] = "%a %b %d %H:%M:%S %Y UTC";
|
|
static char hex_chars[] = "0123456789abcdef";
|
|
static PyObject *empty_tuple = NULL;
|
|
static PyObject *sec_oid_name_to_value = NULL;
|
|
static PyObject *sec_oid_value_to_name = NULL;
|
|
static PyObject *ckm_name_to_value = NULL;
|
|
static PyObject *ckm_value_to_name = NULL;
|
|
static PyObject *cka_name_to_value = NULL;
|
|
static PyObject *cka_value_to_name = NULL;
|
|
static PyObject *general_name_name_to_value = NULL;
|
|
static PyObject *general_name_value_to_name = NULL;
|
|
static PyObject *crl_reason_name_to_value = NULL;
|
|
static PyObject *crl_reason_value_to_name = NULL;
|
|
static PyObject *pkcs12_cipher_name_to_value = NULL;
|
|
static PyObject *pkcs12_cipher_value_to_name = NULL;
|
|
|
|
static PyTypeObject PK11SymKeyType;
|
|
static PyTypeObject PK11ContextType;
|
|
static PyTypeObject SecItemType;
|
|
static PyTypeObject PK11SymKeyType;
|
|
static PyTypeObject AVAType;
|
|
static PyTypeObject RDNType;
|
|
static PyTypeObject DNType;
|
|
static PyTypeObject CertVerifyLogType;
|
|
|
|
/* === Forward Declarations */
|
|
|
|
static PyTypeObject CertificateType;
|
|
static PyTypeObject PK11SlotType;
|
|
|
|
/* === Prototypes === */
|
|
|
|
static PyObject *
|
|
obj_to_hex(PyObject *obj, int octets_per_line, char *separator);
|
|
|
|
static PyObject *
|
|
raw_data_to_hex(unsigned char *data, int data_len, int octets_per_line, char *separator);
|
|
|
|
static SECStatus
|
|
sec_strip_tag_and_length(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_context_specific_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
secitem_to_pystr_hex(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_any_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_set_or_str_secitem_to_pylist_of_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
boolean_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_boolean_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
integer_secitem_to_pylong(SECItem *item);
|
|
|
|
static PyObject *
|
|
integer_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_integer_secitem_to_pystr(SECItem *item);
|
|
|
|
static bool
|
|
is_oid_string(const char *oid_string);
|
|
|
|
static SECOidTag
|
|
ava_name_to_oid_tag(const char *name);
|
|
|
|
static PyObject *
|
|
oid_secitem_to_pystr_desc(SECItem *oid);
|
|
|
|
static PyObject *
|
|
oid_secitem_to_pyint_tag(SECItem *oid);
|
|
|
|
static PyObject *
|
|
oid_secitem_to_pystr_dotted_decimal(SECItem *oid);
|
|
|
|
static PyObject *
|
|
der_oid_secitem_to_pystr_desc(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_utc_time_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_generalized_time_secitem_to_pystr(SECItem *item);
|
|
|
|
static PRTime
|
|
time_choice_secitem_to_prtime(SECItem *item);
|
|
|
|
static PyObject *
|
|
time_choice_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_octet_secitem_to_pystr(SECItem *item, int octets_per_line, char *separator);
|
|
|
|
static PyObject *
|
|
ascii_string_secitem_to_escaped_ascii_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_ascii_string_secitem_to_escaped_ascii_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_utf8_string_secitem_to_pyunicode(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_bmp_string_secitem_to_pyunicode(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_universal_string_secitem_to_pyunicode(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_bit_string_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
der_universal_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
ip_addr_secitem_to_pystr(SECItem *item);
|
|
|
|
static PyObject *
|
|
CERTGeneralName_to_pystr_with_label(CERTGeneralName *general_name);
|
|
|
|
static PyObject *
|
|
CERTGeneralName_to_pystr(CERTGeneralName *general_name);
|
|
|
|
static PyObject *
|
|
cert_oid_tag_name(PyObject *self, PyObject *args);
|
|
|
|
static PyObject *
|
|
cert_trust_flags_str(unsigned int flags, RepresentationKind repr_kind);
|
|
|
|
static PyObject *
|
|
SecItem_new_from_SECItem(const SECItem *item, SECItemKind kind);
|
|
|
|
static PyObject *
|
|
SecItem_new_alloc(size_t len, SECItemType type, SECItemKind kind);
|
|
|
|
static PyObject *
|
|
pk11_md5_digest(PyObject *self, PyObject *args);
|
|
|
|
static PyObject *
|
|
pk11_sha1_digest(PyObject *self, PyObject *args);
|
|
|
|
static PyObject *
|
|
pk11_sha256_digest(PyObject *self, PyObject *args);
|
|
|
|
static PyObject *
|
|
pk11_sha512_digest(PyObject *self, PyObject *args);
|
|
|
|
static PyObject *
|
|
PyPK11Context_new_from_PK11Context(PK11Context *pk11_context);
|
|
|
|
static PyObject *
|
|
PyPK11SymKey_new_from_PK11SymKey(PK11SymKey *pk11_sym_key);
|
|
|
|
static PyObject *
|
|
key_mechanism_type_to_pystr(CK_MECHANISM_TYPE mechanism);
|
|
|
|
static PyObject *
|
|
pk11_attribute_type_to_pystr(CK_ATTRIBUTE_TYPE type);
|
|
|
|
static PyObject *
|
|
SignedCRL_new_from_CERTSignedCRL(CERTSignedCrl *signed_crl);
|
|
|
|
static PyObject *
|
|
AVA_repr(AVA *self);
|
|
|
|
static bool
|
|
CERTRDN_has_tag(CERTRDN *rdn, int tag);
|
|
|
|
static PyObject *
|
|
CERTAVA_value_to_pystr(CERTAVA *ava);
|
|
|
|
static Py_ssize_t
|
|
CERTRDN_ava_count(CERTRDN *rdn);
|
|
|
|
static Py_ssize_t
|
|
DN_length(DN *self);
|
|
|
|
static PyObject *
|
|
DN_item(DN *self, register Py_ssize_t i);
|
|
|
|
static PyObject *
|
|
general_name_type_to_pystr(CERTGeneralNameType type);
|
|
|
|
static PyObject *
|
|
CERTGeneralName_type_string_to_pystr(CERTGeneralName *general_name);
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_general_names_tuple(CRLDistributionPt *self, RepresentationKind repr_kind);
|
|
|
|
PyObject *
|
|
GeneralName_new_from_CERTGeneralName(CERTGeneralName *name);
|
|
|
|
static Py_ssize_t
|
|
AuthKeyID_general_names_count(AuthKeyID *self);
|
|
|
|
static PyObject *
|
|
AuthKeyID_general_names_tuple(AuthKeyID *self, RepresentationKind repr_kind);
|
|
|
|
static int
|
|
set_thread_local(const char *name, PyObject *obj);
|
|
|
|
static PyObject *
|
|
get_thread_local(const char *name);
|
|
|
|
#if 0 /* not currently used */
|
|
static int
|
|
del_thread_local(const char *name);
|
|
#endif
|
|
|
|
static PyObject *
|
|
SECItem_to_hex(SECItem *item, int octets_per_line, char *separator);
|
|
|
|
static PyObject *
|
|
SECItem_der_to_hex(SECItem *item, int octets_per_line, char *separator);
|
|
|
|
static PyObject *
|
|
cert_x509_key_usage(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
static PyObject *
|
|
cert_x509_cert_type(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
PyObject *
|
|
CRLDistributionPts_new_from_SECItem(SECItem *item);
|
|
|
|
PyObject *
|
|
AuthKeyID_new_from_SECItem(SECItem *item);
|
|
|
|
static PyObject *
|
|
cert_x509_ext_key_usage(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
PyObject *
|
|
BasicConstraints_new_from_SECItem(SECItem *item);
|
|
|
|
static PyObject *
|
|
cert_x509_alt_name(PyObject *self, PyObject *args, PyObject *kwds);
|
|
|
|
PyObject *
|
|
DN_new_from_CERTName(CERTName *name);
|
|
|
|
PyObject *
|
|
AlgorithmID_new_from_SECAlgorithmID(SECAlgorithmID *id);
|
|
|
|
static int
|
|
Certificate_init_from_signed_der_secitem(Certificate *self, SECItem *der);
|
|
|
|
static PyObject *
|
|
Certificate_new_from_signed_der_secitem(SECItem *der);
|
|
|
|
static int
|
|
Certificate_init_from_unsigned_der_secitem(Certificate *self, SECItem *der);
|
|
|
|
static PyObject *
|
|
Certificate_get_subject(Certificate *self, void *closure);
|
|
|
|
static PyObject *
|
|
Certificate_get_issuer(Certificate *self, void *closure);
|
|
|
|
static PyObject *
|
|
Certificate_new_from_CERTCertificate(CERTCertificate *cert);
|
|
|
|
static PyObject *
|
|
fingerprint_format_lines(SECItem *item, int level);
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_item(PKCS12Decoder *self, register Py_ssize_t i);
|
|
|
|
PyObject *
|
|
KEYPQGParams_init_from_SECKEYPQGParams(KEYPQGParams *self, const SECKEYPQGParams *params);
|
|
|
|
static PyObject *
|
|
CertVerifyLog_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
|
|
|
static Py_ssize_t
|
|
CertVerifyLog_length(CertVerifyLog *self);
|
|
|
|
static PyObject *
|
|
CertVerifyLog_item(CertVerifyLog *self, register Py_ssize_t i);
|
|
|
|
/* ==================================== */
|
|
|
|
typedef struct BitStringTableStr {
|
|
int enum_value;
|
|
const char *enum_name;
|
|
const char *enum_description;
|
|
} BitStringTable;
|
|
|
|
#define BITSTRING_TBL_INIT(enum, description) \
|
|
{enum, #enum, description}
|
|
|
|
static BitStringTable CRLReasonDef[] = {
|
|
BITSTRING_TBL_INIT(crlEntryReasonUnspecified, _("Unspecified") ), /* bit 0 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonKeyCompromise, _("Key Compromise") ), /* bit 1 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonCaCompromise, _("CA Compromise") ), /* bit 2 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonAffiliationChanged, _("Affiliation Changed") ), /* bit 3 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonSuperseded, _("Superseded") ), /* bit 4 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonCessationOfOperation, _("Cessation Of Operation")), /* bit 5 */
|
|
BITSTRING_TBL_INIT(crlEntryReasoncertificatedHold, _("Certificate On Hold") ), /* bit 6 */
|
|
BITSTRING_TBL_INIT(-1, NULL ), /* bit 7 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonRemoveFromCRL, _("Remove From CRL") ), /* bit 8 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonPrivilegeWithdrawn, _("Privilege Withdrawn") ), /* bit 9 */
|
|
BITSTRING_TBL_INIT(crlEntryReasonAaCompromise, _("AA Compromise") ), /* bit 10 */
|
|
};
|
|
|
|
static BitStringTable KeyUsageDef[] = {
|
|
BITSTRING_TBL_INIT(KU_DIGITAL_SIGNATURE, _("Digital Signature") ), /* bit 0 */
|
|
BITSTRING_TBL_INIT(KU_NON_REPUDIATION, _("Non-Repudiation") ), /* bit 1 */
|
|
BITSTRING_TBL_INIT(KU_KEY_ENCIPHERMENT, _("Key Encipherment") ), /* bit 2 */
|
|
BITSTRING_TBL_INIT(KU_DATA_ENCIPHERMENT, _("Data Encipherment") ), /* bit 3 */
|
|
BITSTRING_TBL_INIT(KU_KEY_AGREEMENT, _("Key Agreement") ), /* bit 4 */
|
|
BITSTRING_TBL_INIT(KU_KEY_CERT_SIGN, _("Certificate Signing")), /* bit 5 */
|
|
BITSTRING_TBL_INIT(KU_CRL_SIGN, _("CRL Signing") ), /* bit 6 */
|
|
BITSTRING_TBL_INIT(KU_ENCIPHER_ONLY, _("Encipher Only") ), /* bit 7 */
|
|
#ifdef KU_DECIPHER_ONLY
|
|
BITSTRING_TBL_INIT(KU_DECIPHER_ONLY, _("Decipher Only") ), /* bit 8 */
|
|
#endif
|
|
};
|
|
|
|
static BitStringTable CertTypeDef[] = {
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_SSL_CLIENT, _("SSL Client") ), /* bit 0 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_SSL_SERVER, _("SSL Server") ), /* bit 1 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_EMAIL, _("Email") ), /* bit 2 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_OBJECT_SIGNING, _("Object Signing") ), /* bit 3 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_RESERVED, _("Reserved") ), /* bit 4 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_SSL_CA, _("SSL CA") ), /* bit 5 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_EMAIL_CA, _("Email CA") ), /* bit 6 */
|
|
BITSTRING_TBL_INIT(NS_CERT_TYPE_OBJECT_SIGNING_CA, _("Object Signing CA") ), /* bit 7 */
|
|
};
|
|
|
|
/* returns new reference or NULL on error */
|
|
PyObject *
|
|
PyString_UTF8(PyObject *obj, char *name)
|
|
{
|
|
if (PyString_Check(obj)) {
|
|
Py_INCREF(obj);
|
|
return obj;
|
|
}
|
|
|
|
if (PyUnicode_Check(obj)) {
|
|
return PyUnicode_AsUTF8String(obj);
|
|
}
|
|
|
|
PyErr_Format(PyExc_TypeError, "%s must be a string, not %.200s",
|
|
name, Py_TYPE(obj)->tp_name);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* read_data_from_file(PyObject *file_arg)
|
|
*
|
|
* :Parameters:
|
|
* file_arg : file name or file object
|
|
* If string treat as file path to open and read,
|
|
* if file object read from file object.
|
|
*
|
|
* Read the contents of a file and return as a PyString object.
|
|
* If file is a string then treat it as a file pathname and open
|
|
* and read the contents of that file. If file is a file object
|
|
* then read the contents from the file object
|
|
*/
|
|
static PyObject *
|
|
read_data_from_file(PyObject *file_arg)
|
|
{
|
|
PyObject *py_file=NULL;
|
|
PyObject *py_file_contents=NULL;
|
|
|
|
if (PyString_Check(file_arg) || PyUnicode_Check(file_arg)) {
|
|
if ((py_file = PyFile_FromString(PyString_AsString(file_arg), "r")) == NULL) {
|
|
return NULL;
|
|
}
|
|
} else if (PyFile_Check(file_arg)) {
|
|
py_file = file_arg;
|
|
Py_INCREF(py_file);
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "Bad file, must be pathname or file object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_file_contents = PyObject_CallMethod(py_file, "read", "")) == NULL) {
|
|
Py_DECREF(py_file);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(py_file);
|
|
|
|
return py_file_contents;
|
|
}
|
|
|
|
static SECStatus
|
|
secport_ucs2_swap_bytes(SECItem *ucs2_item)
|
|
{
|
|
unsigned int i;
|
|
unsigned char tmp;
|
|
|
|
if ((ucs2_item == NULL) || (ucs2_item->len % 2)) {
|
|
return SECFailure;
|
|
}
|
|
|
|
for (i = 0; i < ucs2_item->len; i += 2) {
|
|
tmp = ucs2_item->data[i];
|
|
ucs2_item->data[i] = ucs2_item->data[i+1];
|
|
ucs2_item->data[i+1] = tmp;
|
|
}
|
|
return SECSuccess;
|
|
}
|
|
|
|
static PRBool
|
|
secport_ucs2_to_utf8(PRBool to_unicode,
|
|
unsigned char *in_buf, unsigned int in_buf_len,
|
|
unsigned char *out_buf, unsigned int max_out_buf_len, unsigned int *out_buf_len,
|
|
PRBool swap_bytes)
|
|
{
|
|
SECItem src_item = {siBuffer, NULL, 0};
|
|
SECItem *swapped_item = NULL;
|
|
PRBool result;
|
|
|
|
/* If converting Unicode to ASCII, swap bytes before conversion as neccessary. */
|
|
if (!to_unicode && swap_bytes) {
|
|
SECItem in_buf_item = {siBuffer, NULL, 0};
|
|
|
|
in_buf_item.data = in_buf;
|
|
in_buf_item.len = in_buf_len;
|
|
swapped_item = SECITEM_DupItem(&in_buf_item);
|
|
|
|
if (secport_ucs2_swap_bytes(swapped_item) != SECSuccess) {
|
|
SECITEM_ZfreeItem(swapped_item, PR_TRUE);
|
|
return PR_FALSE;
|
|
}
|
|
|
|
src_item = *swapped_item;
|
|
|
|
} else {
|
|
src_item.data = in_buf;
|
|
src_item.len = in_buf_len;
|
|
}
|
|
|
|
/* Perform the conversion. */
|
|
result = PORT_UCS2_UTF8Conversion(to_unicode, src_item.data, src_item.len,
|
|
out_buf, max_out_buf_len, out_buf_len);
|
|
if (swapped_item)
|
|
SECITEM_ZfreeItem(swapped_item, PR_TRUE);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* NSS WART
|
|
* NSS encodes a bit string in a SECItem by setting the len field
|
|
* to a bit count and stripping off the leading "unused" octet.
|
|
*/
|
|
static int
|
|
der_bitstring_to_nss_bitstring(SECItem *dst, SECItem *src) {
|
|
unsigned long data_len;
|
|
int src_len;
|
|
unsigned char *src_data, octet, unused;
|
|
|
|
if (!src || !dst) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return SECFailure;
|
|
}
|
|
|
|
src_len = src->len;
|
|
src_data = src->data;
|
|
|
|
/* First octet is ASN1 type */
|
|
if (src_len <= 0) goto bad_data;
|
|
octet = *src_data++; src_len--;
|
|
|
|
if ((octet & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_BIT_STRING)
|
|
goto bad_data;
|
|
|
|
/* Next octets are ASN1 length */
|
|
if (src_len <= 0) goto bad_data;
|
|
octet = *src_data++; src_len--;
|
|
|
|
data_len = octet;
|
|
if (data_len & 0x80) {
|
|
int len_count = data_len & 0x7f;
|
|
|
|
if (len_count > src_len)
|
|
goto bad_data;
|
|
|
|
for (data_len = 0, octet = *src_data++, src_len--;
|
|
len_count;
|
|
len_count--, octet = *src_data++, src_len--) {
|
|
data_len = (data_len << 8) | octet;
|
|
}
|
|
}
|
|
|
|
/* After ASN1 length comes one octet containing the unused bit count */
|
|
if (src_len <= 0) goto bad_data;
|
|
unused = *src_data++; src_len--;
|
|
|
|
if (data_len <= 1) {
|
|
goto bad_data;
|
|
} else {
|
|
data_len--; /* account for unused octet */
|
|
dst->len = (data_len << 3) - (unused & 0x07);
|
|
dst->data = src_len > 0 ? src_data : NULL;
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
bad_data:
|
|
PORT_SetError(SEC_ERROR_BAD_DATA);
|
|
return SECFailure;
|
|
}
|
|
|
|
/*
|
|
* Given a decoded bit string in a SECItem (where len is a bit count and
|
|
* the high bit of data[0] is bit[0] of the bitstring) return a tuple of
|
|
* every enabled bit in the bit string. The members of the tuple come from
|
|
* a table of predined values for the bit string. The repr_kind
|
|
* enumeration specifies what type of item should be put in the tuple, for
|
|
* example the string name for the bit position, or the enumerated constant
|
|
* representing that bit postion, or the bit posisiton.
|
|
*/
|
|
static PyObject *
|
|
bitstr_table_to_tuple(SECItem *bitstr, BitStringTable *table,
|
|
size_t table_len, RepresentationKind repr_kind)
|
|
{
|
|
PyObject *tuple = NULL;
|
|
size_t bitstr_len, len, count, i, j;
|
|
unsigned char *data, octet = 0, mask = 0x80;
|
|
|
|
bitstr_len = bitstr->len;
|
|
len = MIN(table_len, bitstr_len);
|
|
|
|
/*
|
|
* Get a count of how many bits are enabled.
|
|
* Skip any undefined entries in the table.
|
|
*/
|
|
count = 0;
|
|
if (bitstr->data != NULL) {
|
|
for (i = 0, data = bitstr->data; i < len; i++) {
|
|
if ((i % 8) == 0) {
|
|
octet = *data++;
|
|
mask = 0x80;
|
|
}
|
|
if (octet & mask) {
|
|
if (table[i].enum_description) { /* only if defined in table */
|
|
count++;
|
|
}
|
|
}
|
|
mask >>= 1;
|
|
}
|
|
}
|
|
|
|
if ((tuple = PyTuple_New(count)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (count == 0) {
|
|
return tuple;
|
|
}
|
|
|
|
/* Populate the tuple */
|
|
for (i = j = 0, data = bitstr->data; i < len; i++) {
|
|
if ((i % 8) == 0) {
|
|
octet = *data++;
|
|
mask = 0x80;
|
|
}
|
|
if (octet & mask) {
|
|
if (table[i].enum_description) { /* only if defined in table */
|
|
switch(repr_kind) {
|
|
case AsEnum:
|
|
PyTuple_SetItem(tuple, j++, PyInt_FromLong(table[i].enum_value));
|
|
break;
|
|
case AsEnumName:
|
|
PyTuple_SetItem(tuple, j++, PyString_FromString(table[i].enum_name));
|
|
break;
|
|
case AsEnumDescription:
|
|
PyTuple_SetItem(tuple, j++, PyString_FromString(table[i].enum_description));
|
|
break;
|
|
case AsIndex:
|
|
PyTuple_SetItem(tuple, j++, PyInt_FromLong(i));
|
|
break;
|
|
default:
|
|
PyErr_Format(PyExc_ValueError, "Unsupported representation kind (%d)", repr_kind);
|
|
Py_DECREF(tuple);
|
|
return NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
mask >>= 1;
|
|
}
|
|
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *
|
|
crl_reason_bitstr_to_tuple(SECItem *bitstr, RepresentationKind repr_kind)
|
|
{
|
|
size_t table_len;
|
|
|
|
table_len = sizeof(CRLReasonDef) / sizeof(CRLReasonDef[0]);
|
|
return bitstr_table_to_tuple(bitstr, CRLReasonDef, table_len, repr_kind);
|
|
}
|
|
|
|
static PyObject *
|
|
key_usage_bitstr_to_tuple(SECItem *bitstr, RepresentationKind repr_kind)
|
|
{
|
|
size_t table_len;
|
|
|
|
table_len = sizeof(KeyUsageDef) / sizeof(KeyUsageDef[0]);
|
|
return bitstr_table_to_tuple(bitstr, KeyUsageDef, table_len, repr_kind);
|
|
}
|
|
|
|
static PyObject *
|
|
cert_type_bitstr_to_tuple(SECItem *bitstr, RepresentationKind repr_kind)
|
|
{
|
|
size_t table_len;
|
|
|
|
table_len = sizeof(CertTypeDef) / sizeof(CertTypeDef[0]);
|
|
return bitstr_table_to_tuple(bitstr, CertTypeDef, table_len, repr_kind);
|
|
}
|
|
|
|
static PyObject *
|
|
decode_oid_sequence_to_tuple(SECItem *item, RepresentationKind repr_kind)
|
|
{
|
|
int i, n_oids;
|
|
PyObject *tuple;
|
|
CERTOidSequence *os;
|
|
SECItem **op;
|
|
PyObject *py_oid;
|
|
|
|
if (!item || !item->len || !item->data) {
|
|
PyErr_SetString(PyExc_ValueError, "missing DER encoded OID data");
|
|
return NULL;
|
|
}
|
|
|
|
if ((os = CERT_DecodeOidSequence(item)) == NULL) {
|
|
return set_nspr_error("unable to decode OID sequence");
|
|
}
|
|
|
|
/* Get a count of how many OID's there were */
|
|
for(op = os->oids, n_oids = 0; *op; op++, n_oids++);
|
|
|
|
if ((tuple = PyTuple_New(n_oids)) == NULL) {
|
|
CERT_DestroyOidSequence(os);
|
|
return NULL;
|
|
}
|
|
|
|
/* Iterate over each OID and insert into tuple */
|
|
for(op = os->oids, i = 0; *op; op++, i++) {
|
|
switch(repr_kind) {
|
|
case AsObject:
|
|
if ((py_oid = SecItem_new_from_SECItem(*op, SECITEM_oid)) == NULL) {
|
|
Py_DECREF(tuple);
|
|
CERT_DestroyOidSequence(os);
|
|
return NULL;
|
|
}
|
|
break;
|
|
case AsString:
|
|
if ((py_oid = oid_secitem_to_pystr_desc(*op)) == NULL) {
|
|
Py_DECREF(tuple);
|
|
CERT_DestroyOidSequence(os);
|
|
return NULL;
|
|
}
|
|
break;
|
|
case AsDottedDecimal:
|
|
if ((py_oid = oid_secitem_to_pystr_dotted_decimal(*op)) == NULL) {
|
|
Py_DECREF(tuple);
|
|
CERT_DestroyOidSequence(os);
|
|
return NULL;
|
|
}
|
|
break;
|
|
case AsEnum:
|
|
if ((py_oid = oid_secitem_to_pyint_tag(*op)) == NULL) {
|
|
Py_DECREF(tuple);
|
|
CERT_DestroyOidSequence(os);
|
|
return NULL;
|
|
}
|
|
break;
|
|
default:
|
|
PyErr_Format(PyExc_ValueError, "Unsupported representation kind (%d)", repr_kind);
|
|
Py_DECREF(tuple);
|
|
CERT_DestroyOidSequence(os);
|
|
return NULL;
|
|
}
|
|
PyTuple_SetItem(tuple, i, py_oid);
|
|
}
|
|
CERT_DestroyOidSequence(os);
|
|
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTCertList_to_tuple(CERTCertList *cert_list)
|
|
{
|
|
Py_ssize_t n_certs = 0;
|
|
Py_ssize_t i = 0;
|
|
CERTCertListNode *node = NULL;
|
|
PyObject *py_cert = NULL;
|
|
PyObject *tuple = NULL;
|
|
|
|
for (node = CERT_LIST_HEAD(cert_list), n_certs = 0;
|
|
!CERT_LIST_END(node, cert_list);
|
|
node = CERT_LIST_NEXT(node), n_certs++);
|
|
|
|
if ((tuple = PyTuple_New(n_certs)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (node = CERT_LIST_HEAD(cert_list), i = 0;
|
|
!CERT_LIST_END(node, cert_list);
|
|
node = CERT_LIST_NEXT(node), i++) {
|
|
if ((py_cert = Certificate_new_from_CERTCertificate(node->cert)) == NULL) {
|
|
Py_DECREF(tuple);
|
|
return NULL;
|
|
}
|
|
PyTuple_SetItem(tuple, i, py_cert);
|
|
}
|
|
return tuple;
|
|
}
|
|
|
|
/* NSS WART: CERT_CopyAVA is hidden, but we need it, copied here from secname.c */
|
|
CERTAVA *
|
|
CERT_CopyAVA(PRArenaPool *arena, CERTAVA *from)
|
|
{
|
|
CERTAVA *ava;
|
|
int rv;
|
|
|
|
ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
|
|
if (ava) {
|
|
rv = SECITEM_CopyItem(arena, &ava->type, &from->type);
|
|
if (rv) goto loser;
|
|
rv = SECITEM_CopyItem(arena, &ava->value, &from->value);
|
|
if (rv) goto loser;
|
|
}
|
|
return ava;
|
|
|
|
loser:
|
|
return NULL;
|
|
}
|
|
|
|
static SECStatus
|
|
CERT_CopyGeneralName(PRArenaPool *arena, CERTGeneralName **pdst, CERTGeneralName *src)
|
|
{
|
|
SECStatus result = SECSuccess;
|
|
void *mark = NULL;
|
|
CERTGeneralName *dst;
|
|
|
|
/*
|
|
* NSS WART
|
|
* There is no public API to create a CERTGeneralName, copy it, or free it.
|
|
* You don't know what arena was used to create the general name.
|
|
* GeneralNames are linked in a list, this makes it difficult for a
|
|
* general name to exist independently, it would have been better if there
|
|
* was a list container independent general names could be placed in,
|
|
* then you wouldn't have to worry about the link fields in each independent name.
|
|
*
|
|
* The logic here is copied from cert_CopyOneGeneralName in certdb/genname.c
|
|
*/
|
|
|
|
if (!arena) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return SECFailure;
|
|
}
|
|
|
|
if (!src) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return SECFailure;
|
|
}
|
|
|
|
mark = PORT_ArenaMark(arena);
|
|
|
|
if ((dst = PORT_ArenaZNew(arena, CERTGeneralName)) == NULL) {
|
|
result = SECFailure;
|
|
goto exit;
|
|
}
|
|
|
|
dst->l.prev = dst->l.next = &dst->l;
|
|
dst->type = src->type;
|
|
|
|
switch (src->type) {
|
|
case certDirectoryName:
|
|
if ((result = SECITEM_CopyItem(arena, &dst->derDirectoryName,
|
|
&src->derDirectoryName)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
if ((result = CERT_CopyName(arena, &dst->name.directoryName,
|
|
&src->name.directoryName)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
break;
|
|
|
|
case certOtherName:
|
|
if ((result = SECITEM_CopyItem(arena, &dst->name.OthName.name,
|
|
&src->name.OthName.name)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
if ((result = SECITEM_CopyItem(arena, &dst->name.OthName.oid,
|
|
&src->name.OthName.oid)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if ((result = SECITEM_CopyItem(arena, &dst->name.other,
|
|
&src->name.other)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
exit:
|
|
if (result == SECSuccess) {
|
|
*pdst = dst;
|
|
PORT_ArenaUnmark(arena, mark);
|
|
} else {
|
|
*pdst = NULL;
|
|
PORT_ArenaRelease(arena, mark);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
CERTGeneralName_list_count(CERTGeneralName *head)
|
|
{
|
|
CERTGeneralName *cur;
|
|
Py_ssize_t count;
|
|
|
|
count = 0;
|
|
if (!head) {
|
|
return count;
|
|
}
|
|
|
|
cur = head;
|
|
do {
|
|
count++;
|
|
cur = CERT_GetNextGeneralName(cur);
|
|
} while (cur != head);
|
|
|
|
return count;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTGeneralName_list_to_tuple(CERTGeneralName *head, RepresentationKind repr_kind)
|
|
{
|
|
CERTGeneralName *cur;
|
|
Py_ssize_t n_names, i;
|
|
PyObject *names;
|
|
|
|
n_names = CERTGeneralName_list_count(head);
|
|
|
|
if ((names = PyTuple_New(n_names)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (n_names == 0) {
|
|
return names;
|
|
}
|
|
|
|
i = 0;
|
|
cur = head;
|
|
do {
|
|
PyObject *name;
|
|
|
|
switch(repr_kind) {
|
|
case AsObject:
|
|
name = GeneralName_new_from_CERTGeneralName(cur);
|
|
break;
|
|
case AsString:
|
|
name = CERTGeneralName_to_pystr(cur);
|
|
break;
|
|
case AsTypeString:
|
|
name = CERTGeneralName_type_string_to_pystr(cur);
|
|
break;
|
|
case AsTypeEnum:
|
|
name = PyInt_FromLong(cur->type);
|
|
break;
|
|
case AsLabeledString:
|
|
name = CERTGeneralName_to_pystr_with_label(cur);
|
|
break;
|
|
default:
|
|
PyErr_Format(PyExc_ValueError, "Unsupported representation kind (%d)", repr_kind);
|
|
Py_DECREF(names);
|
|
return NULL;
|
|
}
|
|
PyTuple_SetItem(names, i, name);
|
|
cur = CERT_GetNextGeneralName(cur);
|
|
i++;
|
|
} while (cur != head);
|
|
|
|
|
|
return names;
|
|
}
|
|
|
|
static SECStatus
|
|
CERT_CopyGeneralNameList(PRArenaPool *arena, CERTGeneralName **pdst, CERTGeneralName *src)
|
|
{
|
|
SECStatus result = SECSuccess;
|
|
void *mark = NULL;
|
|
CERTGeneralName *src_head, *dst_head;
|
|
CERTGeneralName *cur, *prev;
|
|
|
|
/*
|
|
* NSS WART
|
|
* There is no publice API to copy a list of GeneralNames.
|
|
*
|
|
* GeneralNames are an exception to all other NSS data containers.
|
|
* Normally homogeneous collections are stored in a array of pointers to
|
|
* the items with the last array element being NULL. However GeneralNames are
|
|
* exception, they embed a linked list for assembling them in a list. Not only
|
|
* is this an awkward deviation but it means the GeneralName cannot belong to
|
|
* more than one collection.
|
|
*
|
|
* The logic here is copied from CERT_CopyGeneralName in certdb/genname.c
|
|
*
|
|
* The linked list is circular. The logic to stop traversal is if the link
|
|
* pointed to by CERT_GetNextGeneralName/CERT_GetPrevGeneralName is the same
|
|
* as the GeneralName the traversal started with.
|
|
*/
|
|
|
|
if (!arena) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return SECFailure;
|
|
}
|
|
|
|
if (!src) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return SECFailure;
|
|
}
|
|
|
|
mark = PORT_ArenaMark(arena);
|
|
|
|
src_head = src;
|
|
dst_head = cur = NULL;
|
|
do {
|
|
prev = cur;
|
|
if (CERT_CopyGeneralName(arena, &cur, src) != SECSuccess) {
|
|
result = SECFailure;
|
|
goto exit;
|
|
}
|
|
if (dst_head == NULL) { /* first node */
|
|
dst_head = cur;
|
|
prev = cur;
|
|
}
|
|
|
|
cur->l.next = &dst_head->l; /* tail node's next points to head */
|
|
cur->l.prev = &prev->l; /* tail node's prev points to prev */
|
|
dst_head->l.prev = &cur->l; /* head's prev points to tail node */
|
|
prev->l.next = &cur->l; /* prev node's next point to tail node */
|
|
|
|
src = CERT_GetNextGeneralName(src);
|
|
} while (src != src_head);
|
|
|
|
exit:
|
|
if (result == SECSuccess) {
|
|
*pdst = dst_head;
|
|
PORT_ArenaUnmark(arena, mark);
|
|
} else {
|
|
*pdst = NULL;
|
|
PORT_ArenaRelease(arena, mark);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static SECStatus
|
|
CERT_CopyCRLDistributionPoint(PRArenaPool *arena, CRLDistributionPoint **pdst, CRLDistributionPoint *src)
|
|
{
|
|
SECStatus result = SECSuccess;
|
|
CERTRDN *rdn;
|
|
void *mark = NULL;
|
|
CRLDistributionPoint *dst;
|
|
SECItem tmp_item;
|
|
|
|
/*
|
|
* NSS WART
|
|
* There is no public API to create a CRLDistributionPoint or copy it.
|
|
*/
|
|
mark = PORT_ArenaMark(arena);
|
|
|
|
if ((dst = PORT_ArenaZNew(arena, CRLDistributionPoint)) == NULL) {
|
|
result = SECFailure;
|
|
goto exit;
|
|
}
|
|
|
|
switch((dst->distPointType = src->distPointType)) {
|
|
case generalName:
|
|
if ((result = CERT_CopyGeneralNameList(arena,
|
|
&dst->distPoint.fullName,
|
|
src->distPoint.fullName)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
break;
|
|
case relativeDistinguishedName:
|
|
if ((rdn = CERT_CreateRDN(arena, NULL)) == NULL) {
|
|
result = SECFailure;
|
|
goto exit;
|
|
}
|
|
dst->distPoint.relativeName = *rdn;
|
|
if ((result = CERT_CopyRDN(arena,
|
|
&dst->distPoint.relativeName,
|
|
&src->distPoint.relativeName)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
break;
|
|
default:
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
result = SECFailure;
|
|
goto exit;
|
|
}
|
|
|
|
if ((result = SECITEM_CopyItem(arena, &dst->reasons, &src->reasons)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* WARNING: NSS WART
|
|
* src->bitsmap is a SECItem whose length is a bit count and whose data
|
|
* omits the leading DER bitstring "unused" octet.
|
|
*/
|
|
|
|
tmp_item = src->bitsmap;
|
|
DER_ConvertBitString(&tmp_item); /* make len a byte count */
|
|
if ((result = SECITEM_CopyItem(arena, &dst->bitsmap, &tmp_item)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
dst->bitsmap.len = src->bitsmap.len;
|
|
|
|
if (src->crlIssuer) {
|
|
if ((result = CERT_CopyGeneralName(arena, &dst->crlIssuer, src->crlIssuer)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* WARNING: we don't copy these because they're only used during decoding:
|
|
* derDistPoint, derRelativeName, derCrlIssuer, derFullName
|
|
*/
|
|
|
|
exit:
|
|
if (result == SECSuccess) {
|
|
*pdst = dst;
|
|
PORT_ArenaUnmark(arena, mark);
|
|
} else {
|
|
*pdst = NULL;
|
|
PORT_ArenaRelease(arena, mark);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* NSS WART
|
|
* There is no public API to copy a CERTAuthKeyID
|
|
*/
|
|
static SECStatus
|
|
CERT_CopyAuthKeyID(PRArenaPool *arena, CERTAuthKeyID **pdst, CERTAuthKeyID *src)
|
|
{
|
|
SECStatus result = SECSuccess;
|
|
void *mark = NULL;
|
|
CERTAuthKeyID *dst;
|
|
|
|
mark = PORT_ArenaMark(arena);
|
|
|
|
if ((dst = PORT_ArenaZNew(arena, CERTAuthKeyID)) == NULL) {
|
|
result = SECFailure;
|
|
goto exit;
|
|
}
|
|
|
|
if ((result = SECITEM_CopyItem(arena, &dst->keyID, &src->keyID)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((result = CERT_CopyGeneralNameList(arena, &dst->authCertIssuer,
|
|
src->authCertIssuer)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((result = SECITEM_CopyItem(arena, &dst->authCertSerialNumber,
|
|
&src->authCertSerialNumber)) != SECSuccess) {
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if (result == SECSuccess) {
|
|
*pdst = dst;
|
|
PORT_ArenaUnmark(arena, mark);
|
|
} else {
|
|
*pdst = NULL;
|
|
PORT_ArenaRelease(arena, mark);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static int
|
|
oid_tag_from_name(const char *name)
|
|
{
|
|
PyObject *py_name;
|
|
PyObject *py_lower_name;
|
|
PyObject *py_value;
|
|
int oid_tag;
|
|
|
|
if ((py_name = PyString_FromString(name)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
Py_DECREF(py_name);
|
|
return -1;
|
|
}
|
|
|
|
if ((py_value = PyDict_GetItem(sec_oid_name_to_value, py_lower_name)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "oid tag name not found: %s", PyString_AsString(py_name));
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
return -1;
|
|
}
|
|
|
|
oid_tag = PyInt_AsLong(py_value);
|
|
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
|
|
return oid_tag;
|
|
}
|
|
|
|
static PyObject *
|
|
oid_tag_name_from_tag(int oid_tag)
|
|
{
|
|
PyObject *py_value;
|
|
PyObject *py_name;
|
|
|
|
if ((py_value = PyInt_FromLong(oid_tag)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_name = PyDict_GetItem(sec_oid_value_to_name, py_value)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "oid tag not found: %#x", oid_tag);
|
|
Py_DECREF(py_value);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_value);
|
|
Py_INCREF(py_name);
|
|
|
|
return py_name;
|
|
}
|
|
|
|
static int
|
|
get_oid_tag_from_object(PyObject *obj)
|
|
{
|
|
int oid_tag = SEC_OID_UNKNOWN;
|
|
|
|
if (PyString_Check(obj) || PyUnicode_Check(obj)) {
|
|
PyObject *py_obj_string_utf8 = NULL;
|
|
char *type_string;
|
|
|
|
if (PyString_Check(obj)) {
|
|
py_obj_string_utf8 = obj;
|
|
Py_INCREF(py_obj_string_utf8);
|
|
} else {
|
|
py_obj_string_utf8 = PyUnicode_AsUTF8String(obj);
|
|
}
|
|
|
|
if ((type_string = PyString_AsString(py_obj_string_utf8)) == NULL) {
|
|
Py_DECREF(py_obj_string_utf8);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* First see if it's a canonical name,
|
|
* if not try a dotted-decimal OID,
|
|
* if not then try tag name.
|
|
*/
|
|
if ((oid_tag = ava_name_to_oid_tag(type_string)) == SEC_OID_UNKNOWN) {
|
|
if (is_oid_string(type_string)) { /* is dotted-decimal OID */
|
|
SECItem item;
|
|
|
|
item.data = NULL;
|
|
item.len = 0;
|
|
|
|
/* Convert dotted-decimal OID string to SECItem */
|
|
if (SEC_StringToOID(NULL, &item, type_string, 0) != SECSuccess) {
|
|
Py_DECREF(py_obj_string_utf8);
|
|
PyErr_Format(PyExc_ValueError, "failed to convert oid string \"%s\" to SECItem",
|
|
type_string);
|
|
return -1;
|
|
}
|
|
/* Get the OID tag from the SECItem */
|
|
if ((oid_tag = SECOID_FindOIDTag(&item)) == SEC_OID_UNKNOWN) {
|
|
Py_DECREF(py_obj_string_utf8);
|
|
SECITEM_FreeItem(&item, PR_FALSE);
|
|
PyErr_Format(PyExc_ValueError, "could not convert \"%s\" to OID tag", type_string);
|
|
return -1;
|
|
}
|
|
SECITEM_FreeItem(&item, PR_FALSE);
|
|
} else {
|
|
oid_tag = oid_tag_from_name(type_string);
|
|
}
|
|
}
|
|
Py_DECREF(py_obj_string_utf8);
|
|
} else if (PyInt_Check(obj)) {
|
|
oid_tag = PyInt_AsLong(obj);
|
|
} else if (PySecItem_Check(obj)) {
|
|
oid_tag = SECOID_FindOIDTag(&((SecItem *)obj)->item);
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError, "oid must be a string, an integer, or a SecItem, not %.200s",
|
|
Py_TYPE(obj)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
return oid_tag;
|
|
}
|
|
|
|
static bool
|
|
is_oid_string(const char *oid_string)
|
|
{
|
|
const char *p;
|
|
int n_integers, n_dots;
|
|
|
|
n_integers = n_dots = 0;
|
|
p = oid_string;
|
|
if (strncasecmp("OID.", p, 4) == 0) p += 4; /* skip optional OID. prefix */
|
|
while (*p) {
|
|
if (isdigit(*p)) {
|
|
n_integers++;
|
|
for (p++; *p && isdigit(*p); p++); /* consume rest of digits in integer */
|
|
} else if (*p == '.') { /* found a dot */
|
|
n_dots++;
|
|
p++;
|
|
} else { /* not a dot or digit */
|
|
if (isspace(*p)) { /* permit trailing white space */
|
|
for (p++; *p && isspace(*p); p++);
|
|
if (!*p) break;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return (n_integers > 0) && (n_integers == n_dots+1);
|
|
}
|
|
|
|
static const char *
|
|
ava_oid_tag_to_name(SECOidTag tag)
|
|
{
|
|
const DnAvaProps *ava = dn_ava_props;
|
|
|
|
for (ava = dn_ava_props;
|
|
ava->oid_tag != tag && ava->oid_tag != SEC_OID_UNKNOWN;
|
|
ava++);
|
|
|
|
return (ava->oid_tag != SEC_OID_UNKNOWN) ? ava->name : NULL;
|
|
}
|
|
|
|
static int
|
|
ava_oid_tag_to_value_type(SECOidTag tag)
|
|
{
|
|
const DnAvaProps *ava = dn_ava_props;
|
|
|
|
for (ava = dn_ava_props;
|
|
ava->oid_tag != tag && ava->oid_tag != SEC_OID_UNKNOWN;
|
|
ava++);
|
|
|
|
return (ava->oid_tag != SEC_OID_UNKNOWN) ? ava->value_type : SEC_ASN1_UTF8_STRING;
|
|
}
|
|
|
|
/*
|
|
* Given a canonical ava name (e.g. "CN") return the oid tag for it. Case
|
|
* is not significant. If not found SEC_OID_UNKNOWN is returned.
|
|
*/
|
|
static SECOidTag
|
|
ava_name_to_oid_tag(const char *name)
|
|
{
|
|
const DnAvaProps *ava = dn_ava_props;
|
|
|
|
for (ava = dn_ava_props;
|
|
ava->oid_tag != SEC_OID_UNKNOWN && strcasecmp(ava->name, name);
|
|
ava++);
|
|
|
|
return ava->oid_tag;
|
|
}
|
|
|
|
static int
|
|
_AddIntConstantWithLookup(PyObject *module, const char *name, long value, const char *prefix,
|
|
PyObject *name_to_value, PyObject *value_to_name)
|
|
{
|
|
PyObject *module_dict;
|
|
PyObject *py_name = NULL;
|
|
PyObject *py_name_sans_prefix = NULL;
|
|
PyObject *py_lower_name = NULL;
|
|
PyObject *py_value = NULL;
|
|
|
|
if (!PyModule_Check(module)) {
|
|
PyErr_SetString(PyExc_TypeError, "_AddIntConstantWithLookup() needs module as first arg");
|
|
return -1;
|
|
}
|
|
|
|
if ((module_dict = PyModule_GetDict(module)) == NULL) {
|
|
PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
|
|
PyModule_GetName(module));
|
|
return -1;
|
|
}
|
|
|
|
if ((py_name = PyString_FromString(name)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
Py_DECREF(py_name);
|
|
return -1;
|
|
}
|
|
|
|
if ((py_value = PyInt_FromLong(value)) == NULL) {
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
return -1;
|
|
}
|
|
|
|
if (PyDict_SetItem(module_dict, py_name, py_value) != 0) {
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
Py_DECREF(py_value);
|
|
return -1;
|
|
}
|
|
|
|
if (PyDict_SetItem(value_to_name, py_value, py_name) != 0) {
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
Py_DECREF(py_value);
|
|
return -1;
|
|
}
|
|
|
|
if (PyDict_SetItem(name_to_value, py_lower_name, py_value) != 0) {
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
Py_DECREF(py_value);
|
|
return -1;
|
|
}
|
|
|
|
if (prefix) {
|
|
size_t prefix_len = strlen(prefix);
|
|
|
|
if (strlen(name) > prefix_len &&
|
|
strncasecmp(prefix, name, prefix_len) == 0) {
|
|
|
|
if ((py_name_sans_prefix = PyString_FromString(PyString_AS_STRING(py_lower_name) + prefix_len)) == NULL) {
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_lower_name);
|
|
Py_DECREF(py_value);
|
|
return -1;
|
|
}
|
|
|
|
if (PyDict_SetItem(name_to_value, py_name_sans_prefix, py_value) != 0) {
|
|
Py_DECREF(py_name);
|
|
Py_DECREF(py_name_sans_prefix);
|
|
Py_DECREF(py_lower_name);
|
|
Py_DECREF(py_value);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
Py_DECREF(py_name);
|
|
Py_XDECREF(py_name_sans_prefix);
|
|
Py_DECREF(py_lower_name);
|
|
Py_DECREF(py_value);
|
|
return 0;
|
|
}
|
|
|
|
/* Set object in thread local storage under name, return 0 for success, -1 on failure */
|
|
static int
|
|
set_thread_local(const char *name, PyObject *obj)
|
|
{
|
|
PyObject *tdict;
|
|
PyObject *thread_local_dict;
|
|
|
|
/* Get this threads thread local dict */
|
|
if ((tdict = PyThreadState_GetDict()) == NULL) {
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot get thread state");
|
|
return -1;
|
|
}
|
|
|
|
/* Get our (i.e. NSS's) thread local dict */
|
|
if ((thread_local_dict = PyDict_GetItemString(tdict, NSS_THREAD_LOCAL_KEY)) == NULL) {
|
|
/*
|
|
* Our thread local dict does not yet exist so create it
|
|
* and set it in the thread's thread local dict.
|
|
*/
|
|
if ((thread_local_dict = PyDict_New()) == NULL) {
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot create thread local data dict");
|
|
return -1;
|
|
}
|
|
if (PyDict_SetItemString(tdict, NSS_THREAD_LOCAL_KEY, thread_local_dict) < 0) {
|
|
Py_DECREF(thread_local_dict);
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot store thread local data dict");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (PyDict_SetItemString(thread_local_dict, name, obj) < 0) {
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot store object in thread local data dict");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Same return behavior as PyDict_GetItem() */
|
|
static PyObject *
|
|
get_thread_local(const char *name)
|
|
{
|
|
PyObject *tdict;
|
|
PyObject *thread_local_dict;
|
|
|
|
/* Get this threads thread local dict */
|
|
if ((tdict = PyThreadState_GetDict()) == NULL) {
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot get thread state");
|
|
return NULL;
|
|
}
|
|
|
|
/* Get our (i.e. NSS's) thread local dict */
|
|
if ((thread_local_dict = PyDict_GetItemString(tdict, NSS_THREAD_LOCAL_KEY)) == NULL) {
|
|
/*
|
|
* Our thread local dict does not yet exist thus the item can't be
|
|
* in the dict, thus it's not found.
|
|
*/
|
|
return NULL;
|
|
}
|
|
|
|
return PyDict_GetItemString(thread_local_dict, name);
|
|
}
|
|
|
|
#if 0 /* not currently used */
|
|
/* Remove named item from thread local storage, return 0 for success, -1 on failure */
|
|
static int
|
|
del_thread_local(const char *name)
|
|
{
|
|
PyObject *tdict;
|
|
PyObject *thread_local_dict;
|
|
|
|
/* Get this threads thread local dict */
|
|
if ((tdict = PyThreadState_GetDict()) == NULL) {
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot get thread state");
|
|
return -1;
|
|
}
|
|
|
|
/* Get our (i.e. NSS's) thread local dict */
|
|
if ((thread_local_dict = PyDict_GetItemString(tdict, NSS_THREAD_LOCAL_KEY)) == NULL) {
|
|
/*
|
|
* Our thread local dict does not yet exist thus the item can't be
|
|
* in the dict, thus it cannot be deleted, implicit success.
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
return PyDict_DelItemString(thread_local_dict, name);
|
|
}
|
|
#endif
|
|
|
|
static int
|
|
PRTimeConvert(PyObject *obj, PRTime *param)
|
|
{
|
|
PRTime time;
|
|
|
|
if (PyFloat_Check(obj)) {
|
|
LL_D2L(time, PyFloat_AsDouble(obj));
|
|
*param = time;
|
|
return 1;
|
|
}
|
|
|
|
if (PyInt_Check(obj)) {
|
|
LL_I2L(time, PyInt_AsLong(obj)); /* FIXME: should be PyLong_AsLongLong? */
|
|
*param = time;
|
|
return 1;
|
|
}
|
|
|
|
if (PyNone_Check(obj)) {
|
|
time = PR_Now();
|
|
*param = time;
|
|
return 1;
|
|
}
|
|
|
|
PyErr_Format(PyExc_TypeError, "must be int, float or None, not %.50s",
|
|
Py_TYPE(obj)->tp_name);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
PK11SlotOrNoneConvert(PyObject *obj, PyObject **param)
|
|
{
|
|
if (PyPK11Slot_Check(obj)) {
|
|
*param = obj;
|
|
return 1;
|
|
}
|
|
|
|
if (PyNone_Check(obj)) {
|
|
*param = NULL;
|
|
return 1;
|
|
}
|
|
|
|
PyErr_Format(PyExc_TypeError, "must be %.50s or None, not %.50s",
|
|
PK11SlotType.tp_name, Py_TYPE(obj)->tp_name);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
SecItemOrNoneConvert(PyObject *obj, PyObject **param)
|
|
{
|
|
if (PySecItem_Check(obj)) {
|
|
*param = obj;
|
|
return 1;
|
|
}
|
|
|
|
if (PyNone_Check(obj)) {
|
|
*param = NULL;
|
|
return 1;
|
|
}
|
|
|
|
PyErr_Format(PyExc_TypeError, "must be %.50s or None, not %.50s",
|
|
SecItemType.tp_name, Py_TYPE(obj)->tp_name);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
TupleOrNoneConvert(PyObject *obj, PyObject **param)
|
|
{
|
|
if (PyTuple_Check(obj)) {
|
|
*param = obj;
|
|
return 1;
|
|
}
|
|
|
|
if (PyNone_Check(obj)) {
|
|
*param = NULL;
|
|
return 1;
|
|
}
|
|
|
|
PyErr_Format(PyExc_TypeError, "must be %.50s or None, not %.50s",
|
|
PyTuple_Type.tp_name, Py_TYPE(obj)->tp_name);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
SymKeyOrNoneConvert(PyObject *obj, PyObject **param)
|
|
{
|
|
if (PySymKey_Check(obj)) {
|
|
*param = obj;
|
|
return 1;
|
|
}
|
|
|
|
if (PyNone_Check(obj)) {
|
|
*param = NULL;
|
|
return 1;
|
|
}
|
|
|
|
PyErr_Format(PyExc_TypeError, "must be %.50s or None, not %.50s",
|
|
PK11SymKeyType.tp_name, Py_TYPE(obj)->tp_name);
|
|
return 0;
|
|
}
|
|
|
|
static const char *
|
|
pk11_disabled_reason_str(reason)
|
|
{
|
|
static char buf[80];
|
|
|
|
switch(reason) {
|
|
case PK11_DIS_NONE:
|
|
return _("no reason");
|
|
case PK11_DIS_USER_SELECTED:
|
|
return _("user disabled");
|
|
case PK11_DIS_COULD_NOT_INIT_TOKEN:
|
|
return _("could not initialize token");
|
|
case PK11_DIS_TOKEN_VERIFY_FAILED:
|
|
return _("could not verify token");
|
|
case PK11_DIS_TOKEN_NOT_PRESENT:
|
|
return _("token not present");
|
|
default:
|
|
snprintf(buf, sizeof(buf), "unknown(%#x)", reason);
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
static const char *
|
|
pk11_disabled_reason_name(reason)
|
|
{
|
|
static char buf[80];
|
|
|
|
switch(reason) {
|
|
case PK11_DIS_NONE: return "PK11_DIS_NONE";
|
|
case PK11_DIS_USER_SELECTED: return "PK11_DIS_USER_SELECTED";
|
|
case PK11_DIS_COULD_NOT_INIT_TOKEN: return "PK11_DIS_COULD_NOT_INIT_TOKEN";
|
|
case PK11_DIS_TOKEN_VERIFY_FAILED: return "PK11_DIS_TOKEN_VERIFY_FAILED";
|
|
case PK11_DIS_TOKEN_NOT_PRESENT: return "PK11_DIS_TOKEN_NOT_PRESENT";
|
|
default:
|
|
snprintf(buf, sizeof(buf), "unknown(%#x)", reason);
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
static const char *
|
|
key_type_str(KeyType key_type)
|
|
{
|
|
static char buf[80];
|
|
|
|
switch(key_type) {
|
|
case nullKey: return "NULL";
|
|
case rsaKey: return "RSA";
|
|
case dsaKey: return "DSA";
|
|
case fortezzaKey: return "Fortezza";
|
|
case dhKey: return "Diffie Helman";
|
|
case keaKey: return "Key Exchange Algorithm";
|
|
case ecKey: return "Elliptic Curve";
|
|
default:
|
|
snprintf(buf, sizeof(buf), "unknown(%#x)", key_type);
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
|
|
static const char *
|
|
oid_tag_str(SECOidTag tag)
|
|
{
|
|
static char buf[80];
|
|
|
|
SECOidData *oiddata;
|
|
|
|
if ((oiddata = SECOID_FindOIDByTag(tag)) != NULL) {
|
|
return oiddata->desc;
|
|
}
|
|
snprintf(buf, sizeof(buf), "unknown(%#x)", tag);
|
|
return buf;
|
|
}
|
|
|
|
static PyObject *
|
|
obj_sprintf(const char *fmt, ...)
|
|
{
|
|
va_list va;
|
|
Py_ssize_t n_fmts, i;
|
|
PyObject *args = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *py_fmt = NULL;
|
|
PyObject *result = NULL;
|
|
const char *s;
|
|
|
|
for (s = fmt, n_fmts = 0; *s; s++) {
|
|
if (*s == '%') {
|
|
if (s > fmt) {
|
|
if (s[-1] != '%') {
|
|
n_fmts++;
|
|
}
|
|
} else {
|
|
n_fmts++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((args = PyTuple_New(n_fmts)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
va_start(va, fmt);
|
|
for (i = 0; i < n_fmts; i++) {
|
|
obj = va_arg(va, PyObject *);
|
|
Py_INCREF(obj);
|
|
PyTuple_SetItem(args, i, obj);
|
|
}
|
|
va_end(va);
|
|
|
|
if ((py_fmt = PyString_FromString(fmt)) == NULL) {
|
|
Py_DECREF(args);
|
|
return NULL;
|
|
}
|
|
|
|
result = PyString_Format(py_fmt, args);
|
|
Py_DECREF(py_fmt);
|
|
Py_DECREF(args);
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyObject *
|
|
obj_to_hex(PyObject *obj, int octets_per_line, char *separator)
|
|
{
|
|
unsigned char *data = NULL;
|
|
Py_ssize_t data_len;
|
|
|
|
if (PyObject_AsReadBuffer(obj, (void *)&data, &data_len))
|
|
return NULL;
|
|
|
|
return raw_data_to_hex(data, data_len, octets_per_line, separator);
|
|
|
|
}
|
|
|
|
/* see cert_data_to_hex() for documentation */
|
|
static PyObject *
|
|
raw_data_to_hex(unsigned char *data, int data_len, int octets_per_line, char *separator)
|
|
{
|
|
int separator_len = 0;
|
|
char *separator_end = NULL;
|
|
char *src=NULL, *dst=NULL;
|
|
int line_size = 0;
|
|
unsigned char octet = 0;
|
|
int num_lines = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *line = NULL;
|
|
int line_number, i, j;
|
|
int num_octets = 0;
|
|
|
|
if (octets_per_line < 0)
|
|
octets_per_line = 0;
|
|
|
|
if (!separator)
|
|
separator = "";
|
|
|
|
separator_len = strlen(separator);
|
|
separator_end = separator + separator_len;
|
|
|
|
if (octets_per_line == 0) {
|
|
num_octets = data_len;
|
|
line_size = (num_octets * 2) + ((num_octets-1) * separator_len);
|
|
if (line_size < 0) line_size = 0;
|
|
|
|
if ((line = PyString_FromStringAndSize(NULL, line_size)) == NULL) {
|
|
return NULL;
|
|
}
|
|
dst = PyString_AS_STRING(line);
|
|
for (i = 0; i < data_len; i++) {
|
|
octet = data[i];
|
|
*dst++ = hex_chars[(octet & 0xF0) >> 4];
|
|
*dst++ = hex_chars[octet & 0xF];
|
|
if (i < data_len-1)
|
|
for (src = separator; src < separator_end; *dst++ = *src++);
|
|
}
|
|
return line;
|
|
} else {
|
|
num_lines = (data_len + octets_per_line - 1) / octets_per_line;
|
|
if (num_lines < 0) num_lines = 0;
|
|
|
|
if ((lines = PyList_New(num_lines)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (i = line_number = 0; i < data_len;) {
|
|
num_octets = data_len - i;
|
|
if (num_octets > octets_per_line) {
|
|
num_octets = octets_per_line;
|
|
line_size = num_octets*(2+separator_len);
|
|
} else {
|
|
line_size = (num_octets * 2) + ((num_octets-1) * separator_len);
|
|
}
|
|
|
|
if (line_size < 0) line_size = 0;
|
|
if ((line = PyString_FromStringAndSize(NULL, line_size)) == NULL) {
|
|
Py_DECREF(lines);
|
|
return NULL;
|
|
}
|
|
dst = PyString_AS_STRING(line);
|
|
for (j = 0; j < num_octets && i < data_len; i++, j++) {
|
|
octet = data[i];
|
|
*dst++ = hex_chars[(octet & 0xF0) >> 4];
|
|
*dst++ = hex_chars[octet & 0xF];
|
|
if (i < data_len-1)
|
|
for (src = separator; src < separator_end; *dst++ = *src++);
|
|
}
|
|
PyList_SetItem(lines, line_number++, line);
|
|
}
|
|
return lines;
|
|
}
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_data_to_hex_doc,
|
|
"data_to_hex(data, octets_per_line=0, separator=':') -> string or list of strings\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : buffer\n\
|
|
Binary data\n\
|
|
octets_per_line : integer\n\
|
|
Number of octets formatted on one line, if 0 then\n\
|
|
return a single string instead of an array of lines\n\
|
|
separator : string\n\
|
|
String used to seperate each octet\n\
|
|
If None it will be as if the empty string had been\n\
|
|
passed and no separator will be used.\n\
|
|
\n\
|
|
Format the binary data as hex string(s).\n\
|
|
Either a list of strings is returned or a single string.\n\
|
|
\n\
|
|
If octets_per_line is greater than zero then a list of\n\
|
|
strings will be returned where each string contains\n\
|
|
octets_per_line number of octets (except for the last\n\
|
|
string in the list which will contain the remainder of the\n\
|
|
octets). Returning a list of \"lines\" makes it convenient\n\
|
|
for a caller to format a block of hexadecimal data with line\n\
|
|
wrapping. If octets_per_line is greater than zero indicating\n\
|
|
a list result is desired a list is always returned even if\n\
|
|
the number of octets would produce only a single line.\n\
|
|
\n\
|
|
If octets_per_line is zero then a single string is returned,\n\
|
|
(no line splitting is performed). This is the default.\n\
|
|
\n\
|
|
The separator string is used to separate each octet. If None\n\
|
|
it will be as if the empty string had been passed and no\n\
|
|
separator will be used.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_data_to_hex(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"data", "octets_per_line", "separator", NULL};
|
|
PyObject *obj = NULL;
|
|
int octets_per_line = 0;
|
|
char *separator = HEX_SEPARATOR_DEFAULT;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iz:cert_data_to_hex", kwlist,
|
|
&obj, &octets_per_line, &separator))
|
|
return NULL;
|
|
|
|
return obj_to_hex(obj, octets_per_line, separator);
|
|
}
|
|
|
|
PyDoc_STRVAR(read_hex_doc,
|
|
"read_hex(input, separators=\" ,:\\t\\n\") -> buffer\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
input : string\n\
|
|
string containing hexadecimal data\n\
|
|
separators : string or None\n\
|
|
string containing set of separator characters\n\
|
|
Any character encountered during parsing which is in\n\
|
|
this string will be skipped and considered a separator\n\
|
|
between pairs of hexadecimal characters.\n\
|
|
\n\
|
|
Parse a string containing hexadecimal data and return a buffer\n\
|
|
object containing the binary octets. Each octet in the string is\n\
|
|
represented as a pair of case insensitive hexadecimal characters\n\
|
|
(0123456789abcdef). Each octet must be a pair of\n\
|
|
characters. Octets may optionally be preceded by 0x or 0X. Octets\n\
|
|
may be separated by separator characters specified in the\n\
|
|
separators string. The separators string is a set of\n\
|
|
characters. Any character in the separators character set will be\n\
|
|
ignored when it occurs between octets. If no separators should be\n\
|
|
considered then pass an empty string.\n\
|
|
\n\
|
|
Using the default separators each of these strings is valid input\n\
|
|
representing the same 8 octet sequence:\n\
|
|
\n\
|
|
01, 23, 45, 67, 89, ab, cd, ef\n\
|
|
01, 23, 45, 67, 89, AB, CD, EF\n\
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef\n\
|
|
01:23:45:67:89:ab:cd:ef\n\
|
|
0123456789abcdef\n\
|
|
01 23 45 67 89 ab cd ef\n\
|
|
0x010x230x450x670x890xab0xcd0xef\n\
|
|
");
|
|
static PyObject *
|
|
read_hex(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"input", "separators", NULL};
|
|
const char *input;
|
|
const char *separators = " ,:\t\n";
|
|
size_t input_len, separators_len;
|
|
Py_ssize_t n_octets;
|
|
unsigned char octet, *data;
|
|
const char *src, *input_end;
|
|
const char *sep, *separators_end;
|
|
PyObject *py_out_buf;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:read_hex", kwlist,
|
|
&input, &separators))
|
|
return NULL;
|
|
|
|
input_len = strlen(input);
|
|
src = input;
|
|
input_end = input + input_len;
|
|
separators_len = strlen(separators);
|
|
n_octets = 0;
|
|
|
|
/*
|
|
* The maximum number of octets is half the string length
|
|
* because they must occur in pairs. If there are separators
|
|
* in the string then the number of octets will be less than
|
|
* half. Thus len/2 is an upper bound.
|
|
*/
|
|
if ((data = PyMem_Malloc(input_len/2)) == NULL) {
|
|
return PyErr_NoMemory();
|
|
}
|
|
|
|
separators_end = separators + separators_len;
|
|
while (src < input_end) {
|
|
for (; *src; src++) {
|
|
for (sep = separators; sep < separators_end && *src != *sep; sep++);
|
|
if (sep == separators_end) break;
|
|
}
|
|
if (!*src) break;
|
|
if (src[0] == '0' && (tolower(src[1]) == 'x')) src +=2; /* skip 0x or 0X */
|
|
octet = 0;
|
|
switch (tolower(src[0])) {
|
|
case '0': octet = 0x0 << 4; break;
|
|
case '1': octet = 0x1 << 4; break;
|
|
case '2': octet = 0x2 << 4; break;
|
|
case '3': octet = 0x3 << 4; break;
|
|
case '4': octet = 0x4 << 4; break;
|
|
case '5': octet = 0x5 << 4; break;
|
|
case '6': octet = 0x6 << 4; break;
|
|
case '7': octet = 0x7 << 4; break;
|
|
case '8': octet = 0x8 << 4; break;
|
|
case '9': octet = 0x9 << 4; break;
|
|
case 'a': octet = 0xa << 4; break;
|
|
case 'b': octet = 0xb << 4; break;
|
|
case 'c': octet = 0xc << 4; break;
|
|
case 'd': octet = 0xd << 4; break;
|
|
case 'e': octet = 0xe << 4; break;
|
|
case 'f': octet = 0xf << 4; break;
|
|
default:
|
|
PyMem_Free(data);
|
|
PyErr_Format(PyExc_ValueError, "invalid hexadecimal string beginning at offset %d \"%s\"",
|
|
src - input, src);
|
|
return NULL;
|
|
}
|
|
switch (tolower(src[1])) {
|
|
case '0': octet |= 0x0; break;
|
|
case '1': octet |= 0x1; break;
|
|
case '2': octet |= 0x2; break;
|
|
case '3': octet |= 0x3; break;
|
|
case '4': octet |= 0x4; break;
|
|
case '5': octet |= 0x5; break;
|
|
case '6': octet |= 0x6; break;
|
|
case '7': octet |= 0x7; break;
|
|
case '8': octet |= 0x8; break;
|
|
case '9': octet |= 0x9; break;
|
|
case 'a': octet |= 0xa; break;
|
|
case 'b': octet |= 0xb; break;
|
|
case 'c': octet |= 0xc; break;
|
|
case 'd': octet |= 0xd; break;
|
|
case 'e': octet |= 0xe; break;
|
|
case 'f': octet |= 0xf; break;
|
|
default:
|
|
PyMem_Free(data);
|
|
PyErr_Format(PyExc_ValueError, "invalid hexadecimal string beginning at offset %d \"%s\"",
|
|
src - input, src);
|
|
return NULL;
|
|
}
|
|
src += 2;
|
|
data[n_octets++] = octet;
|
|
}
|
|
|
|
if ((py_out_buf = PyString_FromStringAndSize((char *)data, n_octets)) == NULL) {
|
|
PyMem_Free(data);
|
|
return NULL;
|
|
}
|
|
PyMem_Free(data);
|
|
|
|
return py_out_buf;
|
|
}
|
|
|
|
static SECStatus
|
|
sec_strip_tag_and_length(SECItem *item)
|
|
{
|
|
unsigned int start;
|
|
|
|
if (!item || !item->data || item->len < 2) { /* must be at least tag and length */
|
|
return SECFailure;
|
|
}
|
|
start = ((item->data[1] & 0x80) ? (item->data[1] & 0x7f) + 2 : 2);
|
|
if (item->len < start) {
|
|
return SECFailure;
|
|
}
|
|
item->data += start;
|
|
item->len -= start;
|
|
return SECSuccess;
|
|
}
|
|
|
|
/* ================== Convert NSS Object to Python String =================== */
|
|
|
|
static PyObject *
|
|
CERTName_to_pystr(CERTName *cert_name)
|
|
{
|
|
char *name;
|
|
PyObject *py_name = NULL;
|
|
|
|
if (!cert_name) {
|
|
return PyString_FromString("");
|
|
}
|
|
|
|
if ((name = CERT_NameToAscii(cert_name)) == NULL) {
|
|
return PyString_FromString("");
|
|
}
|
|
|
|
py_name = PyString_FromString(name);
|
|
PORT_Free(name);
|
|
return py_name;
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
der_context_specific_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PyObject *py_str = NULL;
|
|
PyObject *hex_str = NULL;
|
|
int type = item->data[0] & SEC_ASN1_TAGNUM_MASK;
|
|
int constructed = item->data[0] & SEC_ASN1_CONSTRUCTED;
|
|
SECItem tmp;
|
|
|
|
if (constructed) {
|
|
py_str = PyString_FromFormat("[%d]", type);
|
|
} else {
|
|
tmp = *item;
|
|
if (sec_strip_tag_and_length(&tmp) == SECSuccess) {
|
|
if ((hex_str = raw_data_to_hex(tmp.data, tmp.len, 0, HEX_SEPARATOR_DEFAULT))) {
|
|
py_str = PyString_FromFormat("[%d] %s", type, PyString_AsString(hex_str));
|
|
Py_DECREF(hex_str);
|
|
}
|
|
}
|
|
if (!py_str) {
|
|
py_str = PyString_FromFormat("[%d]", type);
|
|
}
|
|
}
|
|
|
|
return py_str;
|
|
}
|
|
|
|
static PyObject *
|
|
secitem_to_pystr_hex(SECItem *item)
|
|
{
|
|
return raw_data_to_hex(item->data, item->len, 0, HEX_SEPARATOR_DEFAULT);
|
|
}
|
|
|
|
static PyObject *
|
|
der_any_secitem_to_pystr(SECItem *item)
|
|
{
|
|
if (item && item->len && item->data) {
|
|
switch (item->data[0] & SEC_ASN1_CLASS_MASK) {
|
|
case SEC_ASN1_CONTEXT_SPECIFIC:
|
|
return der_context_specific_secitem_to_pystr(item);
|
|
break;
|
|
case SEC_ASN1_UNIVERSAL:
|
|
return der_universal_secitem_to_pystr(item);
|
|
break;
|
|
default:
|
|
return raw_data_to_hex(item->data, item->len, 0, HEX_SEPARATOR_DEFAULT);
|
|
}
|
|
}
|
|
return PyString_FromString("(null)");
|
|
}
|
|
|
|
|
|
/* return a ASN1 SET or SEQUENCE as a list of strings */
|
|
static PyObject *
|
|
der_set_or_str_secitem_to_pylist_of_pystr(SECItem *item)
|
|
{
|
|
int constructed = item->data[0] & SEC_ASN1_CONSTRUCTED;
|
|
SECItem tmp_item = *item;
|
|
PyObject *py_items = NULL;
|
|
PyObject *py_item = NULL;
|
|
|
|
if (!constructed) {
|
|
return raw_data_to_hex(item->data, item->len, 0, HEX_SEPARATOR_DEFAULT);
|
|
}
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
if ((py_items = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
while (tmp_item.len >= 2) {
|
|
SECItem tmp_item = tmp_item;
|
|
|
|
if (tmp_item.data[1] & 0x80) {
|
|
unsigned int i;
|
|
unsigned int len = tmp_item.data[1] & 0x7f;
|
|
if (len > sizeof tmp_item.len)
|
|
break;
|
|
tmp_item.len = 0;
|
|
for (i = 0; i < len; i++) {
|
|
tmp_item.len = (tmp_item.len << 8) | tmp_item.data[2+i];
|
|
}
|
|
tmp_item.len += len + 2;
|
|
} else {
|
|
tmp_item.len = tmp_item.data[1] + 2;
|
|
}
|
|
if (tmp_item.len > tmp_item.len) {
|
|
tmp_item.len = tmp_item.len;
|
|
}
|
|
tmp_item.data += tmp_item.len;
|
|
tmp_item.len -= tmp_item.len;
|
|
|
|
py_item = der_any_secitem_to_pystr(&tmp_item);
|
|
PyList_Append(py_items, py_item);
|
|
}
|
|
|
|
return py_items;
|
|
}
|
|
|
|
static PyObject *
|
|
boolean_secitem_to_pystr(SECItem *item)
|
|
{
|
|
int val = 0;
|
|
|
|
if (item->data && item->len) {
|
|
val = item->data[0];
|
|
}
|
|
|
|
if (val)
|
|
return PyString_FromString("True");
|
|
else
|
|
return PyString_FromString("False");
|
|
}
|
|
|
|
static PyObject *
|
|
der_boolean_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PyObject *str = NULL;
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) == SECSuccess)
|
|
str = boolean_secitem_to_pystr(&tmp_item);
|
|
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Decodes ASN1 integer. Properly handles large magnitude.
|
|
* PyInt object returned if value fits, PyLong object otherwise.
|
|
*
|
|
* item is a decoded ASN1 integer, if the integer is a DER encoded
|
|
* integer with a tag and length then call encoded_integer_secitem_to_pylong
|
|
*/
|
|
static PyObject *
|
|
integer_secitem_to_pylong(SECItem *item)
|
|
{
|
|
int len;
|
|
unsigned char *data, octet;
|
|
PyObject *l = NULL;
|
|
PyObject *eight = NULL;
|
|
PyObject *new_bits = NULL;
|
|
PyObject *tmp = NULL;
|
|
bool negative;
|
|
|
|
if (!item || !item->len || !item->data) {
|
|
return PyInt_FromLong(0);
|
|
}
|
|
|
|
len = item->len;
|
|
data = item->data;
|
|
octet = *data++;
|
|
negative = octet & 0x80;
|
|
|
|
if (negative) {
|
|
if ((l = PyInt_FromLong(-1)) == NULL) {
|
|
goto error;
|
|
}
|
|
} else {
|
|
if ((l = PyInt_FromLong(0)) == NULL) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
if ((eight = PyInt_FromLong(8)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
while (1) {
|
|
if ((new_bits = PyInt_FromLong(octet)) == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
if ((tmp = PyNumber_Lshift(l, eight)) == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
Py_CLEAR(l);
|
|
|
|
if ((l = PyNumber_Or(tmp, new_bits)) == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
Py_CLEAR(tmp);
|
|
Py_CLEAR(new_bits);
|
|
|
|
if (--len) {
|
|
octet = *data++;
|
|
} else {
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
error:
|
|
Py_CLEAR(l);
|
|
exit:
|
|
Py_XDECREF(eight);
|
|
Py_XDECREF(new_bits);
|
|
Py_XDECREF(tmp);
|
|
return l;
|
|
}
|
|
#if 0
|
|
The following can be used to test integer_secitem_to_pylong()
|
|
#define ASN1_TEST(octets, expect) \
|
|
{ \
|
|
SECItem item; \
|
|
PyObject *py_long = NULL; \
|
|
PyObject *py_str = NULL; \
|
|
\
|
|
item.len = sizeof(octets); \
|
|
item.data = octets; \
|
|
\
|
|
py_long = integer_secitem_to_pylong(&item); \
|
|
py_str = PyObject_Str(py_long); \
|
|
printf("expect %8s got %8s\n", expect, PyString_AsString(py_str)); \
|
|
Py_DECREF(py_long); \
|
|
Py_DECREF(py_str); \
|
|
}
|
|
{
|
|
unsigned char data1[] = {0x48}; /* 72 */
|
|
unsigned char data2[] = {0x7F}; /* 127 */
|
|
unsigned char data3[] = {0x80}; /* -128 */
|
|
unsigned char data4[] = {0x00, 0x80}; /* 128 */
|
|
unsigned char data5[] = {0x96, 0x46}; /* -27066 */
|
|
|
|
ASN1_TEST(data1, "72");
|
|
ASN1_TEST(data2, "127");
|
|
ASN1_TEST(data3, "-128");
|
|
ASN1_TEST(data4, "128");
|
|
ASN1_TEST(data5, "-27066");
|
|
|
|
}
|
|
#endif
|
|
|
|
static PyObject *
|
|
integer_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PyObject *py_int = NULL;
|
|
PyObject *py_str = NULL;
|
|
|
|
if ((py_int = integer_secitem_to_pylong(item)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
py_str = PyObject_Str(py_int);
|
|
|
|
Py_DECREF(py_int);
|
|
return py_str;
|
|
}
|
|
|
|
static PyObject *
|
|
der_integer_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PyObject *py_str = NULL;
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) == SECSuccess)
|
|
py_str = integer_secitem_to_pystr(&tmp_item);
|
|
|
|
return py_str;
|
|
}
|
|
|
|
static PyObject *
|
|
oid_secitem_to_pystr_desc(SECItem *oid)
|
|
{
|
|
SECOidData *oiddata;
|
|
char *oid_string = NULL;
|
|
PyObject *py_oid_str = NULL;
|
|
|
|
if ((oiddata = SECOID_FindOID(oid)) != NULL) {
|
|
return PyString_FromString(oiddata->desc);
|
|
}
|
|
if ((oid_string = CERT_GetOidString(oid)) != NULL) {
|
|
py_oid_str = PyString_FromString(oid_string);
|
|
PR_smprintf_free(oid_string);
|
|
return py_oid_str;
|
|
}
|
|
return obj_to_hex((PyObject *)oid, 0, HEX_SEPARATOR_DEFAULT);
|
|
}
|
|
|
|
static PyObject *
|
|
oid_secitem_to_pyint_tag(SECItem *oid)
|
|
{
|
|
SECOidTag oid_tag;
|
|
|
|
oid_tag = SECOID_FindOIDTag(oid);
|
|
return PyInt_FromLong(oid_tag);
|
|
}
|
|
|
|
static PyObject *
|
|
oid_secitem_to_pystr_dotted_decimal(SECItem *oid)
|
|
{
|
|
char *oid_string = NULL;
|
|
PyObject *py_oid_string;
|
|
|
|
if ((oid_string = CERT_GetOidString(oid)) == NULL) {
|
|
return PyString_FromString("");
|
|
}
|
|
if ((py_oid_string = PyString_FromString(oid_string)) == NULL) {
|
|
PR_smprintf_free(oid_string);
|
|
return NULL;
|
|
}
|
|
PR_smprintf_free(oid_string);
|
|
return py_oid_string;
|
|
}
|
|
|
|
static PyObject *
|
|
der_oid_secitem_to_pystr_desc(SECItem *item)
|
|
{
|
|
PyObject *str = NULL;
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) == SECSuccess)
|
|
str = oid_secitem_to_pystr_desc(&tmp_item);
|
|
|
|
return str;
|
|
}
|
|
|
|
static PyObject *
|
|
der_utc_time_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PRTime pr_time = 0;
|
|
PRExplodedTime exploded_time;
|
|
char time_str[100];
|
|
|
|
if ((DER_UTCTimeToTime(&pr_time, item) != SECSuccess)) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
PR_ExplodeTime(pr_time, PR_GMTParameters, &exploded_time);
|
|
PR_FormatTime(time_str, sizeof(time_str), time_format, &exploded_time);
|
|
|
|
return PyString_FromString(time_str);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
der_generalized_time_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PRTime pr_time = 0;
|
|
PRExplodedTime exploded_time;
|
|
char time_str[100];
|
|
|
|
if ((DER_GeneralizedTimeToTime(&pr_time, item) != SECSuccess)) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
PR_ExplodeTime(pr_time, PR_GMTParameters, &exploded_time);
|
|
PR_FormatTime(time_str, sizeof(time_str), time_format, &exploded_time);
|
|
|
|
return PyString_FromString(time_str);
|
|
}
|
|
|
|
|
|
static PRTime
|
|
time_choice_secitem_to_prtime(SECItem *item)
|
|
{
|
|
PRTime pr_time = 0;
|
|
|
|
switch (item->type) {
|
|
case siUTCTime:
|
|
DER_UTCTimeToTime(&pr_time, item);
|
|
break;
|
|
case siGeneralizedTime:
|
|
DER_GeneralizedTimeToTime(&pr_time, item);
|
|
break;
|
|
default:
|
|
PyErr_SetString(PyExc_ValueError, "unknown sec ANS.1 time type");
|
|
}
|
|
return pr_time;
|
|
}
|
|
|
|
static PyObject *
|
|
time_choice_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PRTime pr_time = 0;
|
|
PRExplodedTime exploded_time;
|
|
char time_str[100];
|
|
|
|
pr_time = time_choice_secitem_to_prtime(item);
|
|
PR_ExplodeTime(pr_time, PR_GMTParameters, &exploded_time);
|
|
PR_FormatTime(time_str, sizeof(time_str), time_format, &exploded_time);
|
|
|
|
return PyString_FromString(time_str);
|
|
}
|
|
|
|
static PyObject *
|
|
der_octet_secitem_to_pystr(SECItem *item, int octets_per_line, char *separator)
|
|
{
|
|
PyObject *str = NULL;
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) == SECSuccess)
|
|
str = raw_data_to_hex(tmp_item.data, tmp_item.len, octets_per_line, separator);
|
|
|
|
return str;
|
|
}
|
|
|
|
static PyObject *
|
|
der_bit_string_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PyObject *str = NULL;
|
|
SECItem tmp_item = *item;
|
|
int unused_bits;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess || tmp_item.len < 2) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
unused_bits = *tmp_item.data++;
|
|
tmp_item.len--;
|
|
|
|
str = raw_data_to_hex(tmp_item.data, tmp_item.len, 0, HEX_SEPARATOR_DEFAULT);
|
|
|
|
if (unused_bits) {
|
|
PyString_ConcatAndDel(&str, PyString_FromFormat("(%d least significant bits unused)", unused_bits));
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
static PyObject *
|
|
ascii_string_secitem_to_escaped_ascii_pystr(SECItem *item)
|
|
{
|
|
PyObject *py_str = NULL;
|
|
size_t escaped_len;
|
|
const unsigned char *s; /* must be unsigned for table indexing to work */
|
|
char *escaped_str, *dst, *src;
|
|
AsciiEscapes *encode;
|
|
unsigned int len;
|
|
|
|
escaped_len = ascii_encoded_strnlen((const char *)item->data, item->len);
|
|
|
|
if ((py_str = PyString_FromStringAndSize(NULL, escaped_len)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
escaped_str = PyString_AS_STRING(py_str);
|
|
|
|
for (s = (unsigned char *)item->data, len = item->len, dst = escaped_str;
|
|
len;
|
|
s++, len--) {
|
|
encode = &ascii_encoding_table[*s];
|
|
for (src = encode->encoded; *src; src++) {
|
|
*dst++ = *src;
|
|
}
|
|
}
|
|
|
|
*dst = 0; /* shouldn't be necessary, PyString's are always NULL terminated */
|
|
|
|
return py_str;
|
|
}
|
|
|
|
static PyObject *
|
|
der_ascii_string_secitem_to_escaped_ascii_pystr(SECItem *item)
|
|
{
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
PyErr_SetString(PyExc_ValueError, "malformed raw ascii string buffer");
|
|
return NULL;
|
|
}
|
|
|
|
return ascii_string_secitem_to_escaped_ascii_pystr(&tmp_item);
|
|
}
|
|
|
|
static PyObject *
|
|
der_utf8_string_secitem_to_pyunicode(SECItem *item)
|
|
{
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
PyErr_SetString(PyExc_ValueError, "malformed raw ASN.1 BMP string buffer");
|
|
return NULL;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8((const char *)tmp_item.data, tmp_item.len, NULL);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
der_bmp_string_secitem_to_pyunicode(SECItem *item)
|
|
{
|
|
SECItem tmp_item = *item;
|
|
int byte_order = 1; /* 1 = big endian, asn.1 DER is always big endian */
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
PyErr_SetString(PyExc_ValueError, "malformed raw ASN.1 BMP string buffer");
|
|
return NULL;
|
|
}
|
|
|
|
if (tmp_item.len % 2) {
|
|
PyErr_SetString(PyExc_ValueError, "raw ASN.1 BMP string length must be multiple of 2");
|
|
return NULL;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF16((const char *)tmp_item.data, tmp_item.len,
|
|
NULL, &byte_order);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
der_universal_string_secitem_to_pyunicode(SECItem *item)
|
|
{
|
|
SECItem tmp_item = *item;
|
|
int byte_order = 1; /* 1 = big endian, asn.1 DER is always big endian */
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
PyErr_SetString(PyExc_ValueError, "malformed raw ASN.1 Universal string buffer");
|
|
return NULL;
|
|
}
|
|
|
|
if (tmp_item.len % 4) {
|
|
PyErr_SetString(PyExc_ValueError, "raw ASN.1 Universal string length must be multiple of 4");
|
|
return NULL;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF32((const char *)tmp_item.data, tmp_item.len,
|
|
NULL, &byte_order);
|
|
}
|
|
|
|
static PyObject *
|
|
der_universal_secitem_to_pystr(SECItem *item)
|
|
{
|
|
switch (item->data[0] & SEC_ASN1_TAGNUM_MASK) {
|
|
case SEC_ASN1_ENUMERATED:
|
|
case SEC_ASN1_INTEGER:
|
|
return der_integer_secitem_to_pystr(item);
|
|
case SEC_ASN1_OBJECT_ID:
|
|
return der_oid_secitem_to_pystr_desc(item);
|
|
case SEC_ASN1_BOOLEAN:
|
|
return der_boolean_secitem_to_pystr(item);
|
|
case SEC_ASN1_UTF8_STRING:
|
|
return der_utf8_string_secitem_to_pyunicode(item);
|
|
case SEC_ASN1_PRINTABLE_STRING:
|
|
case SEC_ASN1_VISIBLE_STRING:
|
|
case SEC_ASN1_IA5_STRING:
|
|
case SEC_ASN1_T61_STRING:
|
|
return der_ascii_string_secitem_to_escaped_ascii_pystr(item);
|
|
case SEC_ASN1_GENERALIZED_TIME:
|
|
return der_generalized_time_secitem_to_pystr(item);
|
|
case SEC_ASN1_UTC_TIME:
|
|
return der_utc_time_secitem_to_pystr(item);
|
|
case SEC_ASN1_NULL:
|
|
return PyString_FromString("(null)");
|
|
case SEC_ASN1_SET:
|
|
case SEC_ASN1_SEQUENCE:
|
|
return der_set_or_str_secitem_to_pylist_of_pystr(item);
|
|
case SEC_ASN1_OCTET_STRING:
|
|
return der_octet_secitem_to_pystr(item, 0, HEX_SEPARATOR_DEFAULT);
|
|
case SEC_ASN1_BIT_STRING:
|
|
der_bit_string_secitem_to_pystr(item);
|
|
break;
|
|
case SEC_ASN1_BMP_STRING:
|
|
return der_bmp_string_secitem_to_pyunicode(item);
|
|
case SEC_ASN1_UNIVERSAL_STRING:
|
|
return der_universal_string_secitem_to_pyunicode(item);
|
|
default:
|
|
return raw_data_to_hex(item->data, item->len, 0, HEX_SEPARATOR_DEFAULT);
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_der_universal_secitem_fmt_lines_doc,
|
|
"der_universal_secitem_fmt_lines(sec_item, level=0, octets_per_line=0, separator=':') -> list of (indent, string) tuples\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
sec_item : SecItem object\n\
|
|
A SecItem containing a DER encoded ASN1 universal type\n\
|
|
level : integer\n\
|
|
Initial indentation level, all subsequent indents are relative\n\
|
|
to this starting level.\n\
|
|
octets_per_line : integer\n\
|
|
Number of octets formatted on one line, if 0 then\n\
|
|
return a single string instead of an array of lines\n\
|
|
separator : string\n\
|
|
String used to seperate each octet\n\
|
|
If None it will be as if the empty string had been\n\
|
|
passed and no separator will be used.\n\
|
|
\n\
|
|
Given a SecItem in DER format which encodes a ASN.1 universal\n\
|
|
type convert the item to a string and return a list of\n\
|
|
(indent, string) tuples.\n\
|
|
");
|
|
static PyObject *
|
|
cert_der_universal_secitem_fmt_lines(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", "octets_per_line", "separator", NULL};
|
|
SecItem *py_sec_item = NULL;
|
|
int level = 0;
|
|
int octets_per_line = OCTETS_PER_LINE_DEFAULT;
|
|
char *hex_separator = HEX_SEPARATOR_DEFAULT;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
SECItem *item = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|iiz:der_universal_secitem_fmt_lines", kwlist,
|
|
&SecItemType, &py_sec_item,
|
|
&level, &octets_per_line, &hex_separator))
|
|
return NULL;
|
|
|
|
item = &py_sec_item->item;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
switch (item->data[0] & SEC_ASN1_TAGNUM_MASK) {
|
|
case SEC_ASN1_ENUMERATED:
|
|
case SEC_ASN1_INTEGER:
|
|
obj = der_integer_secitem_to_pystr(item);
|
|
case SEC_ASN1_OBJECT_ID:
|
|
obj = der_oid_secitem_to_pystr_desc(item);
|
|
case SEC_ASN1_BOOLEAN:
|
|
obj = der_boolean_secitem_to_pystr(item);
|
|
case SEC_ASN1_UTF8_STRING:
|
|
obj = der_utf8_string_secitem_to_pyunicode(item);
|
|
case SEC_ASN1_PRINTABLE_STRING:
|
|
case SEC_ASN1_VISIBLE_STRING:
|
|
case SEC_ASN1_IA5_STRING:
|
|
case SEC_ASN1_T61_STRING:
|
|
obj = der_ascii_string_secitem_to_escaped_ascii_pystr(item);
|
|
case SEC_ASN1_GENERALIZED_TIME:
|
|
obj = der_generalized_time_secitem_to_pystr(item);
|
|
case SEC_ASN1_UTC_TIME:
|
|
obj = der_utc_time_secitem_to_pystr(item);
|
|
case SEC_ASN1_NULL:
|
|
obj = PyString_FromString("(null)");
|
|
case SEC_ASN1_SET:
|
|
case SEC_ASN1_SEQUENCE:
|
|
obj = der_set_or_str_secitem_to_pylist_of_pystr(item);
|
|
case SEC_ASN1_OCTET_STRING:
|
|
obj = der_octet_secitem_to_pystr(item, octets_per_line, hex_separator);
|
|
case SEC_ASN1_BIT_STRING:
|
|
der_bit_string_secitem_to_pystr(item);
|
|
break;
|
|
case SEC_ASN1_BMP_STRING:
|
|
obj = der_bmp_string_secitem_to_pyunicode(item);
|
|
case SEC_ASN1_UNIVERSAL_STRING:
|
|
obj = der_universal_string_secitem_to_pyunicode(item);
|
|
default:
|
|
obj = raw_data_to_hex(item->data, item->len, octets_per_line, hex_separator);
|
|
}
|
|
|
|
if (PyList_Check(obj)) {
|
|
APPEND_LINES_AND_CLEAR(lines, obj, level, fail);
|
|
} else {
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj, level, fail);
|
|
}
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
secitem_integer_format_lines(SECItem *item, int level)
|
|
{
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
PyObject *obj_lines = NULL;
|
|
|
|
TraceMethodEnter(NULL);
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (item->len > 8) {
|
|
if ((obj_lines = SECItem_to_hex(item, OCTETS_PER_LINE_DEFAULT, HEX_SEPARATOR_DEFAULT)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_LINES_AND_CLEAR(lines, obj_lines, level, fail);
|
|
} else {
|
|
if ((obj = integer_secitem_to_pylong(item)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj1 = obj_sprintf("%d (%#x)", obj, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(obj);
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj1, level, fail);
|
|
Py_CLEAR(obj1);
|
|
}
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj_lines);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
fingerprint_format_lines(SECItem *item, int level)
|
|
{
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(NULL);
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Fingerprint (MD5)"), level, fail);
|
|
if ((obj = PyString_FromStringAndSize(NULL, MD5_LENGTH)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if (PK11_HashBuf(SEC_OID_MD5, (unsigned char *)PyString_AsString(obj),
|
|
item->data, item->len) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
}
|
|
APPEND_OBJ_TO_HEX_LINES_AND_CLEAR(lines, obj, level+1, fail);
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Fingerprint (SHA1)"), level, fail);
|
|
if ((obj = PyString_FromStringAndSize(NULL, SHA1_LENGTH)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if (PK11_HashBuf(SEC_OID_SHA1, (unsigned char *)PyString_AsString(obj),
|
|
item->data, item->len) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
}
|
|
APPEND_OBJ_TO_HEX_LINES_AND_CLEAR(lines, obj, level+1, fail);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTGeneralName_type_string_to_pystr(CERTGeneralName *general_name)
|
|
{
|
|
|
|
switch(general_name->type) {
|
|
case certOtherName: {
|
|
PyObject *py_oid = oid_secitem_to_pystr_desc(&general_name->name.OthName.oid);
|
|
if (py_oid) {
|
|
PyObject *result = PyString_FromFormat(_("Other Name (%s)"), PyString_AS_STRING(py_oid));
|
|
Py_DECREF(py_oid);
|
|
return result;
|
|
} else {
|
|
return PyString_FromString(_("Other Name"));
|
|
}
|
|
}
|
|
case certRFC822Name:
|
|
return PyString_FromString(_("RFC822 Name"));
|
|
case certDNSName:
|
|
return PyString_FromString(_("DNS name"));
|
|
case certX400Address:
|
|
return PyString_FromString(_("X400 Address"));
|
|
case certDirectoryName:
|
|
return PyString_FromString(_("Directory Name"));
|
|
case certEDIPartyName:
|
|
return PyString_FromString(_("EDI Party"));
|
|
case certURI:
|
|
return PyString_FromString(_("URI"));
|
|
case certIPAddress:
|
|
return PyString_FromString(_("IP Address"));
|
|
case certRegisterID:
|
|
return PyString_FromString(_("Registered ID"));
|
|
default:
|
|
return PyString_FromFormat(_("unknown type [%d]"), (int)general_name->type - 1);
|
|
}
|
|
}
|
|
|
|
static PyObject *
|
|
CERTGeneralName_to_pystr(CERTGeneralName *general_name)
|
|
{
|
|
switch(general_name->type) {
|
|
case certOtherName:
|
|
return der_any_secitem_to_pystr(&general_name->name.OthName.name);
|
|
case certRFC822Name:
|
|
return ascii_string_secitem_to_escaped_ascii_pystr(&general_name->name.other);
|
|
case certDNSName:
|
|
return ascii_string_secitem_to_escaped_ascii_pystr(&general_name->name.other);
|
|
case certX400Address:
|
|
return der_any_secitem_to_pystr(&general_name->name.other);
|
|
case certDirectoryName:
|
|
return CERTName_to_pystr(&general_name->name.directoryName);
|
|
case certEDIPartyName:
|
|
return der_any_secitem_to_pystr(&general_name->name.other);
|
|
case certURI:
|
|
return ascii_string_secitem_to_escaped_ascii_pystr(&general_name->name.other);
|
|
case certIPAddress:
|
|
return ip_addr_secitem_to_pystr(&general_name->name.other);
|
|
case certRegisterID:
|
|
return oid_secitem_to_pystr_desc(&general_name->name.other);
|
|
default:
|
|
PyErr_Format(PyExc_ValueError, _("unknown type [%d]"), (int)general_name->type - 1);
|
|
return NULL;
|
|
|
|
}
|
|
}
|
|
|
|
static PyObject *
|
|
CERTGeneralName_to_pystr_with_label(CERTGeneralName *general_name)
|
|
{
|
|
PyObject *py_label = NULL;
|
|
PyObject *py_value = NULL;
|
|
PyObject *result = NULL;
|
|
|
|
if (!general_name) {
|
|
return NULL;
|
|
}
|
|
|
|
py_label = CERTGeneralName_type_string_to_pystr(general_name);
|
|
py_value = CERTGeneralName_to_pystr(general_name);
|
|
|
|
if (py_label && py_value) {
|
|
result = PyString_FromFormat("%s: %s",
|
|
PyString_AS_STRING(py_label),
|
|
PyString_AS_STRING(py_value));
|
|
} else if (py_value) {
|
|
Py_INCREF(py_value);
|
|
result = py_value;
|
|
}
|
|
|
|
Py_XDECREF(py_label);
|
|
Py_XDECREF(py_value);
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTAVA_value_to_pystr(CERTAVA *ava)
|
|
{
|
|
PyObject *result = NULL;
|
|
SECOidTag oid_tag;
|
|
const char *attr_name;
|
|
char *oid_name;
|
|
char value_buf[1024];
|
|
SECItem *value_item;
|
|
|
|
if (!ava) {
|
|
return PyString_FromString("");
|
|
}
|
|
|
|
value_buf[0] = 0;
|
|
attr_name = NULL;
|
|
oid_name = NULL;
|
|
|
|
/*
|
|
* Get the AVA's attribute name (e.g. type) as a string. If we
|
|
* can't get the canonical name use a dotted-decimal OID
|
|
* representation instead.
|
|
*/
|
|
if ((oid_tag = CERT_GetAVATag(ava)) != -1) {
|
|
attr_name = ava_oid_tag_to_name(oid_tag);
|
|
}
|
|
|
|
if (attr_name == NULL) {
|
|
if ((oid_name = CERT_GetOidString(&ava->type)) == NULL) {
|
|
return set_nspr_error("cannot convert AVA type to OID string");
|
|
}
|
|
}
|
|
|
|
/* Get the AVA's attribute value as a string */
|
|
if ((value_item = CERT_DecodeAVAValue(&ava->value)) == NULL) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
return set_nspr_error("unable to decode AVA value");
|
|
}
|
|
if (CERT_RFC1485_EscapeAndQuote(value_buf, sizeof(value_buf),
|
|
(char *)value_item->data,
|
|
value_item->len) != SECSuccess) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
SECITEM_FreeItem(value_item, PR_TRUE);
|
|
return set_nspr_error("unable to escape AVA value string");
|
|
}
|
|
SECITEM_FreeItem(value_item, PR_TRUE);
|
|
|
|
/* Format "name=value" */
|
|
if ((result = PyString_FromFormat("%s=%s",
|
|
attr_name ? attr_name : oid_name,
|
|
value_buf)) == NULL) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
return NULL;
|
|
}
|
|
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTRDN_to_pystr(CERTRDN *rdn)
|
|
{
|
|
PyObject *result = NULL;
|
|
CERTAVA **avas, *ava;
|
|
SECOidTag oid_tag;
|
|
const char *attr_name;
|
|
char *oid_name;
|
|
bool first;
|
|
char value_buf[1024];
|
|
SECItem *value_item;
|
|
|
|
if (!rdn || !(avas = rdn->avas) || *avas == NULL) {
|
|
return PyString_FromString("");
|
|
}
|
|
|
|
first = true;
|
|
while ((ava = *avas++) != NULL) {
|
|
value_buf[0] = 0;
|
|
attr_name = NULL;
|
|
oid_name = NULL;
|
|
|
|
/*
|
|
* Get the AVA's attribute name (e.g. type) as a string. If we
|
|
* can't get the canonical name use a dotted-decimal OID
|
|
* representation instead.
|
|
*/
|
|
if ((oid_tag = CERT_GetAVATag(ava)) != -1) {
|
|
attr_name = ava_oid_tag_to_name(oid_tag);
|
|
}
|
|
|
|
if (attr_name == NULL) {
|
|
if ((oid_name = CERT_GetOidString(&ava->type)) == NULL) {
|
|
return set_nspr_error("cannot convert AVA type to OID string");
|
|
}
|
|
}
|
|
|
|
/* Get the AVA's attribute value as a string */
|
|
if ((value_item = CERT_DecodeAVAValue(&ava->value)) == NULL) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
return set_nspr_error("unable to decode AVA value");
|
|
}
|
|
if (CERT_RFC1485_EscapeAndQuote(value_buf, sizeof(value_buf),
|
|
(char *)value_item->data,
|
|
value_item->len) != SECSuccess) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
SECITEM_FreeItem(value_item, PR_TRUE);
|
|
return set_nspr_error("unable to escape AVA value string");
|
|
}
|
|
SECITEM_FreeItem(value_item, PR_TRUE);
|
|
|
|
/*
|
|
* Format "name=value", if there is more than one AVA join them
|
|
* together with a "+". Typically there is only one AVA.
|
|
*/
|
|
if (first) {
|
|
if ((result = PyString_FromFormat("%s=%s",
|
|
attr_name ? attr_name : oid_name,
|
|
value_buf)) == NULL) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
PyObject *temp;
|
|
|
|
if ((temp = PyString_FromFormat("+%s=%s",
|
|
attr_name ? attr_name : oid_name,
|
|
value_buf)) == NULL) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
return NULL;
|
|
}
|
|
PyString_ConcatAndDel(&result, temp);
|
|
if (result == NULL) {
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (oid_name) PR_smprintf_free(oid_name);
|
|
first = false;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static PyObject *
|
|
cert_trust_flags_str(unsigned int flags, RepresentationKind repr_kind)
|
|
{
|
|
BIT_FLAGS_TO_LIST_PROLOGUE();
|
|
|
|
#if NSS_VMAJOR >= 3 && NSS_VMINOR >= 13
|
|
BIT_FLAGS_TO_LIST(CERTDB_TERMINAL_RECORD, _("Terminal Record"));
|
|
#else
|
|
BIT_FLAGS_TO_LIST(CERTDB_VALID_PEER, _("Valid Peer"));
|
|
#endif
|
|
BIT_FLAGS_TO_LIST(CERTDB_TRUSTED, _("Trusted"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_SEND_WARN, _("Warn When Sending"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_VALID_CA, _("Valid CA"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_TRUSTED_CA, _("Trusted CA"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_NS_TRUSTED_CA, _("Netscape Trusted CA"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_USER, _("User"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_TRUSTED_CLIENT_CA, _("Trusted Client CA"));
|
|
BIT_FLAGS_TO_LIST(CERTDB_GOVT_APPROVED_CA, _("Step-up"));
|
|
|
|
BIT_FLAGS_TO_LIST_EPILOGUE();
|
|
}
|
|
|
|
static PyObject *
|
|
cert_usage_flags(unsigned int flags, RepresentationKind repr_kind)
|
|
{
|
|
BIT_FLAGS_TO_LIST_PROLOGUE();
|
|
|
|
BIT_FLAGS_TO_LIST(certificateUsageSSLClient, _("SSL Client"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageSSLServer, _("SSL Server"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageSSLServerWithStepUp, _("SSL Server With StepUp"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageSSLCA, _("SSL CA"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageEmailSigner, _("Email Signer"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageEmailRecipient, _("Email Recipient"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageObjectSigner, _("Object Signer"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageUserCertImport, _("User Certificate Import"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageVerifyCA, _("Verify CA"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageProtectedObjectSigner, _("Protected Object Signer"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageStatusResponder, _("Status Responder"));
|
|
BIT_FLAGS_TO_LIST(certificateUsageAnyCA, _("Any CA"));
|
|
|
|
BIT_FLAGS_TO_LIST_EPILOGUE();
|
|
}
|
|
|
|
static PyObject *
|
|
key_usage_flags(unsigned int flags, RepresentationKind repr_kind)
|
|
{
|
|
BIT_FLAGS_TO_LIST_PROLOGUE();
|
|
|
|
BIT_FLAGS_TO_LIST(KU_DIGITAL_SIGNATURE, _("Digital Signature"));
|
|
BIT_FLAGS_TO_LIST(KU_NON_REPUDIATION, _("Non-Repudiation"));
|
|
BIT_FLAGS_TO_LIST(KU_KEY_ENCIPHERMENT, _("Key Encipherment"));
|
|
BIT_FLAGS_TO_LIST(KU_DATA_ENCIPHERMENT, _("Data Encipherment"));
|
|
BIT_FLAGS_TO_LIST(KU_KEY_AGREEMENT, _("Key Agreement"));
|
|
BIT_FLAGS_TO_LIST(KU_KEY_CERT_SIGN, _("Certificate Signing"));
|
|
BIT_FLAGS_TO_LIST(KU_CRL_SIGN, _("CRL Signing"));
|
|
BIT_FLAGS_TO_LIST(KU_ENCIPHER_ONLY, _("Encipher Only"));
|
|
#ifdef KU_DECIPHER_ONLY
|
|
BIT_FLAGS_TO_LIST(KU_DECIPHER_ONLY, _("Decipher Only"));
|
|
#endif
|
|
/*
|
|
* The following flags are not present in certs but appear in
|
|
* CERTVerifyNode when the error is
|
|
* SEC_ERROR_INADEQUATE_KEY_USAGE. This rountine is also used
|
|
* to print those flags.
|
|
*/
|
|
BIT_FLAGS_TO_LIST(KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION, _("Digital Signature or Non-Repudiation"));
|
|
BIT_FLAGS_TO_LIST(KU_KEY_AGREEMENT_OR_ENCIPHERMENT, _("Key Agreement or Data Encipherment"));
|
|
BIT_FLAGS_TO_LIST(KU_NS_GOVT_APPROVED, _("Government Approved"));
|
|
|
|
BIT_FLAGS_TO_LIST_EPILOGUE();
|
|
}
|
|
|
|
static PyObject *
|
|
cert_type_flags(unsigned int flags, RepresentationKind repr_kind)
|
|
{
|
|
BIT_FLAGS_TO_LIST_PROLOGUE();
|
|
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_SSL_CLIENT, _("SSL Client"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_SSL_SERVER, _("SSL Server"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_EMAIL, _("Email"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_OBJECT_SIGNING, _("Object Signing"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_RESERVED, _("Reserved"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_SSL_CA, _("SSL CA"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_EMAIL_CA, _("Email CA"));
|
|
BIT_FLAGS_TO_LIST(NS_CERT_TYPE_OBJECT_SIGNING_CA, _("Object Signing CA"));
|
|
/*
|
|
* The following flags are not actual cert types but they get
|
|
* OR'ed into a cert type bitmask.
|
|
*/
|
|
BIT_FLAGS_TO_LIST(EXT_KEY_USAGE_TIME_STAMP, _("Key Usage Timestamp"));
|
|
BIT_FLAGS_TO_LIST(EXT_KEY_USAGE_STATUS_RESPONDER, _("Key Usage Status Responder"));
|
|
|
|
BIT_FLAGS_TO_LIST_EPILOGUE();
|
|
}
|
|
|
|
static PyObject *
|
|
nss_init_flags(unsigned int flags, RepresentationKind repr_kind)
|
|
{
|
|
BIT_FLAGS_TO_LIST_PROLOGUE();
|
|
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_READONLY, _("Read Only"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_NOCERTDB, _("No Certificate Database"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_NOMODDB, _("No Module Database"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_FORCEOPEN, _("Force Open"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_NOROOTINIT, _("No Root Init"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_OPTIMIZESPACE, _("Optimize Space"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_PK11THREADSAFE, _("PK11 Thread Safe"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_PK11RELOAD, _("PK11 Reload"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_NOPK11FINALIZE, _("No PK11 Finalize"));
|
|
BIT_FLAGS_TO_LIST(NSS_INIT_RESERVED, _("Reserved"));
|
|
|
|
BIT_FLAGS_TO_LIST_EPILOGUE();
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
ip_addr_secitem_to_pystr(SECItem *item)
|
|
{
|
|
PRNetAddr addr;
|
|
char buf[1024];
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
if (item->len == 4) {
|
|
addr.inet.family = PR_AF_INET;
|
|
memcpy(&addr.inet.ip, item->data, item->len);
|
|
} else if (item->len == 16) {
|
|
addr.ipv6.family = PR_AF_INET6;
|
|
memcpy(addr.ipv6.ip.pr_s6_addr, item->data, item->len);
|
|
if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
|
|
/* convert to IPv4. */
|
|
addr.inet.family = PR_AF_INET;
|
|
memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
|
|
memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
|
|
}
|
|
} else {
|
|
return secitem_to_pystr_hex(item);
|
|
}
|
|
|
|
if (PR_NetAddrToString(&addr, buf, sizeof(buf)) != PR_SUCCESS) {
|
|
return secitem_to_pystr_hex(item);
|
|
}
|
|
|
|
return PyString_FromString(buf);
|
|
}
|
|
|
|
static PyObject *
|
|
SECItem_to_hex(SECItem *item, int octets_per_line, char *separator)
|
|
{
|
|
return raw_data_to_hex(item->data, item->len, octets_per_line, separator);
|
|
}
|
|
|
|
static PyObject *
|
|
SECItem_der_to_hex(SECItem *item, int octets_per_line, char *separator)
|
|
{
|
|
SECItem tmp_item = *item;
|
|
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
PyErr_SetString(PyExc_ValueError, "malformed ASN.1 DER data");
|
|
return NULL;
|
|
}
|
|
|
|
return raw_data_to_hex(tmp_item.data, tmp_item.len, octets_per_line, separator);
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =============================== SecItem Class ============================ */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
SecItem_get_type(SecItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->item.type);
|
|
}
|
|
|
|
static PyObject *
|
|
SecItem_get_len(SecItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->item.len);
|
|
}
|
|
|
|
static PyObject *
|
|
SecItem_get_data(SecItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyString_FromStringAndSize((const char *)self->item.data, self->item.len);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef SecItem_getseters[] = {
|
|
{"type", (getter)SecItem_get_type, (setter)NULL,
|
|
"the SecItem type (si* constant)", NULL},
|
|
{"len", (getter)SecItem_get_len, (setter)NULL,
|
|
"number of octets in SecItem buffer", NULL},
|
|
{"data", (getter)SecItem_get_data, (setter)NULL,
|
|
"contents of SecItem buffer", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef SecItem_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(SecItem_get_oid_sequence_doc,
|
|
"get_oid_sequence(sec_item, repr_kind=AsString) -> (obj, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
sec_item : SecItem object\n\
|
|
A SecItem containing a DER encoded sequence of OID's\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsObject\n\
|
|
Each extended key usage will be a SecItem object embedding\n\
|
|
the OID in DER format.\n\
|
|
AsString\n\
|
|
Each extended key usage will be a descriptive string.\n\
|
|
(e.g. \"TLS Web Server Authentication Certificate\")\n\
|
|
AsDottedDecimal\n\
|
|
Each extended key usage will be OID rendered as a dotted decimal string.\n\
|
|
(e.g. \"OID.1.3.6.1.5.5.7.3.1\")\n\
|
|
AsEnum\n\
|
|
Each extended key usage will be OID tag enumeration constant (int).\n\
|
|
(e.g. nss.SEC_OID_EXT_KEY_USAGE_SERVER_AUTH)\n\
|
|
\n\
|
|
Return a tuple of OID's according the representation kind.\n\
|
|
");
|
|
static PyObject *
|
|
SecItem_get_oid_sequence(SecItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"repr_kind", NULL};
|
|
int repr_kind = AsString;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:get_oid_sequence", kwlist,
|
|
&repr_kind))
|
|
return NULL;
|
|
|
|
return decode_oid_sequence_to_tuple(&self->item, repr_kind);
|
|
}
|
|
|
|
PyDoc_STRVAR(SecItem_to_hex_doc,
|
|
"to_hex(octets_per_line=0, separator=':') -> string or list of strings\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
octets_per_line : integer\n\
|
|
Number of octets formatted on one line, if 0 then\n\
|
|
return a single string instead of an array of lines\n\
|
|
separator : string\n\
|
|
String used to seperate each octet\n\
|
|
If None it will be as if the empty string had been\n\
|
|
passed and no separator will be used.\n\
|
|
\n\
|
|
Equivalent to calling data_to_hex(sec_item)\n\
|
|
");
|
|
|
|
static PyObject *
|
|
SecItem_to_hex(SecItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"octets_per_line", "separator", NULL};
|
|
int octets_per_line = 0;
|
|
char *separator = HEX_SEPARATOR_DEFAULT;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iz:to_hex", kwlist,
|
|
&octets_per_line, &separator))
|
|
return NULL;
|
|
|
|
return raw_data_to_hex(self->item.data, self->item.len, octets_per_line, separator);
|
|
}
|
|
|
|
PyDoc_STRVAR(SecItem_der_to_hex_doc,
|
|
"der_to_hex(octets_per_line=0, separator=':') -> string or list of strings\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
octets_per_line : integer\n\
|
|
Number of octets formatted on one line, if 0 then\n\
|
|
return a single string instead of an array of lines\n\
|
|
separator : string\n\
|
|
String used to seperate each octet\n\
|
|
If None it will be as if the empty string had been\n\
|
|
passed and no separator will be used.\n\
|
|
\n\
|
|
Interpret the SecItem as containing DER encoded data consisting\n\
|
|
of a <type,length,value> triplet (e.g. TLV). This function skips\n\
|
|
the type and length components and returns the value component as\n\
|
|
a hexadecimal string or a list of hexidecimal strings with a\n\
|
|
maximum of octets_per_line in each list element. See data_to_hex()\n\
|
|
for a more detailed explanation.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
SecItem_der_to_hex(SecItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"octets_per_line", "separator", NULL};
|
|
int octets_per_line = 0;
|
|
char *separator = HEX_SEPARATOR_DEFAULT;
|
|
SECItem tmp_item = self->item;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iz:der_to_hex", kwlist,
|
|
&octets_per_line, &separator))
|
|
return NULL;
|
|
|
|
|
|
tmp_item = self->item;
|
|
if (sec_strip_tag_and_length(&tmp_item) != SECSuccess) {
|
|
PyErr_SetString(PyExc_ValueError, "malformed ASN.1 DER data");
|
|
return NULL;
|
|
}
|
|
|
|
return raw_data_to_hex(tmp_item.data, tmp_item.len, octets_per_line, separator);
|
|
}
|
|
|
|
static PyMethodDef SecItem_methods[] = {
|
|
{"get_oid_sequence", (PyCFunction)SecItem_get_oid_sequence, METH_NOARGS, SecItem_get_oid_sequence_doc},
|
|
{"to_hex", (PyCFunction)SecItem_to_hex, METH_VARARGS|METH_KEYWORDS, SecItem_to_hex_doc},
|
|
{"der_to_hex", (PyCFunction)SecItem_der_to_hex, METH_VARARGS|METH_KEYWORDS, SecItem_der_to_hex_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
SecItem_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
SecItem *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (SecItem *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
self->item.type = 0;
|
|
self->item.len = 0;
|
|
self->item.data = NULL;
|
|
self->kind = SECITEM_unknown;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
SecItem_dealloc(SecItem* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->item.data) {
|
|
PyMem_FREE(self->item.data);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(SecItem_doc,
|
|
"SecItem(data=None, type=siBuffer)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : any read buffer compatible object (e.g. buffer or string)\n\
|
|
raw data to initialize from\n\
|
|
type : int\n\
|
|
SECItemType constant (e.g. si*)\n\
|
|
\n\
|
|
Encoded data. Used internally by NSS\n\
|
|
");
|
|
static int
|
|
SecItem_init(SecItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"data", "type", NULL};
|
|
const void *buffer = NULL;
|
|
Py_ssize_t buffer_len;
|
|
int type = siBuffer;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z#i:SecItem", kwlist,
|
|
&buffer, &buffer_len, &type))
|
|
return -1;
|
|
|
|
if (buffer) {
|
|
self->kind = SECITEM_buffer;
|
|
self->item.type = type;
|
|
self->item.len = buffer_len;
|
|
if ((self->item.data = PyMem_MALLOC(buffer_len)) == NULL) {
|
|
PyErr_Format(PyExc_MemoryError, "not enough memory to copy buffer of size %d into SecItem",
|
|
buffer_len);
|
|
return -1;
|
|
}
|
|
memmove(self->item.data, buffer, buffer_len);
|
|
} else { /* empty buffer */
|
|
self->kind = SECITEM_buffer;
|
|
self->item.type = siBuffer;
|
|
self->item.len = 0;
|
|
self->item.data = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
SecItem_repr(SecItem *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyObject *
|
|
SecItem_str(SecItem *self)
|
|
{
|
|
PyObject *return_value = NULL;
|
|
|
|
switch(self->kind) {
|
|
case SECITEM_dist_name:
|
|
{
|
|
char *name;
|
|
|
|
if ((name = CERT_DerNameToAscii(&self->item)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
return_value = PyString_FromString(name);
|
|
PORT_Free(name);
|
|
}
|
|
break;
|
|
case SECITEM_algorithm:
|
|
return oid_secitem_to_pystr_desc(&self->item);
|
|
default:
|
|
return_value = obj_to_hex((PyObject *)self, 0, HEX_SEPARATOR_DEFAULT);
|
|
|
|
break;
|
|
}
|
|
return return_value;
|
|
}
|
|
|
|
static int
|
|
SecItem_compare(SecItem *self, SecItem *other)
|
|
{
|
|
if (!PySecItem_Check(other)) {
|
|
PyErr_SetString(PyExc_TypeError, "Bad type, must be SecItem");
|
|
return -1;
|
|
}
|
|
|
|
if (self->item.data == NULL && other->item.data == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (self->item.len > other->item.len) {
|
|
return 1;
|
|
}
|
|
|
|
if (self->item.len < other->item.len) {
|
|
return -1;
|
|
}
|
|
|
|
return memcmp(self->item.data, other->item.data, self->item.len);
|
|
}
|
|
|
|
/* =========================== Buffer Protocol ========================== */
|
|
|
|
static Py_ssize_t
|
|
SecItem_buffer_getbuf(PyObject *obj, Py_ssize_t index, void **ptr)
|
|
{
|
|
SecItem *self = (SecItem *) obj;
|
|
if (index != 0) {
|
|
PyErr_SetString(PyExc_SystemError, "Accessing non-existent segment");
|
|
return -1;
|
|
}
|
|
*ptr = self->item.data;
|
|
return self->item.len;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
SecItem_buffer_getsegcount(PyObject *obj, Py_ssize_t *lenp)
|
|
{
|
|
if (lenp)
|
|
*lenp = 1;
|
|
return 1;
|
|
}
|
|
|
|
static PyBufferProcs SecItem_as_buffer = {
|
|
SecItem_buffer_getbuf, /* bf_getreadbuffer */
|
|
SecItem_buffer_getbuf, /* bf_getwritebuffer */
|
|
SecItem_buffer_getsegcount, /* bf_getsegcount */
|
|
NULL, /* bf_getcharbuffer */
|
|
};
|
|
|
|
static Py_ssize_t
|
|
SecItem_length(SecItem *self)
|
|
{
|
|
return self->item.len;
|
|
}
|
|
|
|
static PyObject *
|
|
SecItem_item(SecItem *self, register Py_ssize_t i)
|
|
{
|
|
char octet;
|
|
|
|
if (i < 0 || i >= self->item.len) {
|
|
PyErr_SetString(PyExc_IndexError, "SecItem index out of range");
|
|
return NULL;
|
|
}
|
|
octet = self->item.data[i];
|
|
return PyString_FromStringAndSize(&octet, 1);
|
|
}
|
|
|
|
/* slice a[i:j] consists of octets a[i] ... a[j-1], j -- may be negative! */
|
|
static PyObject *
|
|
SecItem_slice(SecItem *a, Py_ssize_t i, Py_ssize_t j)
|
|
{
|
|
if (i < 0)
|
|
i = 0;
|
|
if (j < 0)
|
|
j = 0;
|
|
if (j > SecItem_GET_SIZE(a))
|
|
j = SecItem_GET_SIZE(a);
|
|
if (j < i)
|
|
j = i;
|
|
return PyString_FromStringAndSize((const char *)(a->item.data + i), j-i);
|
|
}
|
|
|
|
static PyObject*
|
|
SecItem_subscript(SecItem *self, PyObject* item)
|
|
{
|
|
if (PyIndex_Check(item)) {
|
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
|
if (i == -1 && PyErr_Occurred())
|
|
return NULL;
|
|
if (i < 0)
|
|
i += SecItem_GET_SIZE(self);
|
|
return SecItem_item(self, i);
|
|
}
|
|
else if (PySlice_Check(item)) {
|
|
Py_ssize_t start, stop, step, slice_len, cur, i;
|
|
unsigned char* src;
|
|
unsigned char* dst;
|
|
PyObject* result;
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, SecItem_GET_SIZE(self),
|
|
&start, &stop, &step, &slice_len) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (slice_len <= 0) {
|
|
return PyString_FromStringAndSize("", 0);
|
|
} else if (step == 1) {
|
|
return PyString_FromStringAndSize((char *)self->item.data + start, slice_len);
|
|
} else {
|
|
src = self->item.data;
|
|
if ((result = PyString_FromStringAndSize(NULL, slice_len)) == NULL) {
|
|
return NULL;
|
|
}
|
|
dst = (unsigned char *)PyString_AsString(result);
|
|
for (cur = start, i = 0; i < slice_len; cur += step, i++) {
|
|
dst[i] = src[cur];
|
|
}
|
|
return result;
|
|
}
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError, "SecItem indices must be integers, not %.200s",
|
|
Py_TYPE(item)->tp_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static PySequenceMethods SecItem_as_sequence = {
|
|
(lenfunc)SecItem_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)SecItem_item, /* sq_item */
|
|
(ssizessizeargfunc)SecItem_slice, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyMappingMethods SecItem_as_mapping = {
|
|
(lenfunc)SecItem_length, /* mp_length */
|
|
(binaryfunc)SecItem_subscript, /* mp_subscript */
|
|
0, /* mp_ass_subscript */
|
|
};
|
|
|
|
static PyTypeObject SecItemType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.SecItem", /* tp_name */
|
|
sizeof(SecItem), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)SecItem_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
(cmpfunc)SecItem_compare, /* tp_compare */
|
|
(reprfunc)SecItem_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&SecItem_as_sequence, /* tp_as_sequence */
|
|
&SecItem_as_mapping, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)SecItem_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
&SecItem_as_buffer, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
SecItem_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
SecItem_methods, /* tp_methods */
|
|
SecItem_members, /* tp_members */
|
|
SecItem_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)SecItem_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
SecItem_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
SecItem_new_from_SECItem(const SECItem *item, SECItemKind kind)
|
|
{
|
|
SecItem *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if (!item) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self = (SecItem *) SecItemType.tp_new(&SecItemType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->item.type = item->type;
|
|
self->item.len = item->len;
|
|
if ((self->item.data = PyMem_MALLOC(item->len)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return PyErr_NoMemory();
|
|
}
|
|
memmove(self->item.data, item->data, item->len);
|
|
|
|
self->kind = kind;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
static PyObject *
|
|
SecItem_new_alloc(size_t len, SECItemType type, SECItemKind kind)
|
|
{
|
|
SecItem *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (SecItem *) SecItemType.tp_new(&SecItemType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->item.type = type;
|
|
self->item.len = len;
|
|
if ((self->item.data = PyMem_MALLOC(len)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return PyErr_NoMemory();
|
|
}
|
|
|
|
self->kind = kind;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================ AlgorithmID Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/*
|
|
* NSS WART BEGIN
|
|
*
|
|
* The following have no public definition, copied from secutil.c
|
|
*/
|
|
typedef struct secuPBEParamsStr {
|
|
SECItem salt;
|
|
SECItem iterationCount;
|
|
SECItem keyLength;
|
|
SECAlgorithmID cipherAlg;
|
|
SECAlgorithmID kdfAlg;
|
|
} secuPBEParams;
|
|
|
|
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate);
|
|
|
|
/* SECOID_PKCS5_PBKDF2 */
|
|
const SEC_ASN1Template secuKDF2Params[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
|
|
{ SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
|
|
{ SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
|
|
{ SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
|
|
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
|
|
{ 0 }
|
|
};
|
|
|
|
/* PKCS5v1 & PKCS12 */
|
|
const SEC_ASN1Template secuPBEParamsTemp[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
|
|
{ SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
|
|
{ SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
|
|
{ 0 }
|
|
};
|
|
|
|
/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
|
|
const SEC_ASN1Template secuPBEV2Params[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams)},
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
|
|
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
|
|
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
|
|
{ 0 }
|
|
};
|
|
|
|
/*
|
|
* NSS WART END
|
|
*/
|
|
|
|
#ifdef HAVE_RSA_PSS
|
|
static PyObject *
|
|
RSAPSSParams_format_lines(SECItem *item, int level)
|
|
{
|
|
SECKEYRSAPSSParams params;
|
|
SECAlgorithmID mask_hash_alg;
|
|
PRArenaPool *arena = NULL;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
|
|
/* allocate an arena to use */
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
set_nspr_error(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PORT_Memset(¶ms, 0, sizeof params);
|
|
|
|
if (SEC_QuickDERDecodeItem(arena, ¶ms,
|
|
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
|
|
item) != SECSuccess) {
|
|
goto fail;
|
|
}
|
|
|
|
if (params.hashAlg) {
|
|
obj = oid_secitem_to_pystr_desc(¶ms.hashAlg->algorithm);
|
|
} else {
|
|
obj = PyString_FromString("default, SHA-1");
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Hash algorithm"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if (params.maskAlg) {
|
|
obj = oid_secitem_to_pystr_desc(¶ms.maskAlg->algorithm);
|
|
if (SEC_QuickDERDecodeItem(arena, &mask_hash_alg,
|
|
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
|
|
¶ms.maskAlg->parameters) == SECSuccess) {
|
|
obj1 = oid_secitem_to_pystr_desc(&mask_hash_alg.algorithm);
|
|
} else {
|
|
obj1 = PyString_FromString("Invalid mask generation algorithm parameters");
|
|
}
|
|
} else {
|
|
obj = PyString_FromString("default, MGF1");
|
|
obj1 = PyString_FromString("default, SHA-1");
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Mask Algorithm"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Mask hash algorithm"), obj1, level, fail);
|
|
Py_CLEAR(obj1);
|
|
|
|
if (params.saltLength.data) {
|
|
obj = integer_secitem_to_pystr(¶ms.saltLength);
|
|
} else {
|
|
obj = PyString_FromString("default, 20");
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Salt length"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(lines);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
static PyObject *
|
|
KDF2Params_format_lines(SECItem *item, int level)
|
|
{
|
|
secuPBEParams params;
|
|
PRArenaPool *arena = NULL;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(NULL);
|
|
|
|
/* allocate an arena to use */
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
set_nspr_error(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PORT_Memset(¶ms, 0, sizeof params);
|
|
|
|
if (SEC_QuickDERDecodeItem(arena, ¶ms, secuKDF2Params, item) != SECSuccess) {
|
|
goto fail;
|
|
}
|
|
|
|
obj = secitem_to_pystr_hex(¶ms.salt);
|
|
FMT_OBJ_AND_APPEND(lines, _("Salt"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
obj = integer_secitem_to_pystr(¶ms.iterationCount);
|
|
FMT_OBJ_AND_APPEND(lines, _("Iteration Count"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
obj = integer_secitem_to_pystr(¶ms.iterationCount);
|
|
FMT_OBJ_AND_APPEND(lines, _("Key Length"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
obj = AlgorithmID_new_from_SECAlgorithmID(¶ms.kdfAlg);
|
|
FMT_LABEL_AND_APPEND(lines, _("KDF Algorithm"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS5V2Params_format_lines(SECItem *item, int level)
|
|
{
|
|
secuPBEParams params;
|
|
PRArenaPool *arena = NULL;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(NULL);
|
|
|
|
/* allocate an arena to use */
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
set_nspr_error(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PORT_Memset(¶ms, 0, sizeof params);
|
|
|
|
if (SEC_QuickDERDecodeItem(arena, ¶ms, secuPBEV2Params, item) != SECSuccess) {
|
|
goto fail;
|
|
}
|
|
|
|
obj = AlgorithmID_new_from_SECAlgorithmID(¶ms.kdfAlg);
|
|
FMT_LABEL_AND_APPEND(lines, _("KDF"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
obj = AlgorithmID_new_from_SECAlgorithmID(¶ms.cipherAlg);
|
|
FMT_LABEL_AND_APPEND(lines, _("Cipher"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
PBEParams_format_lines(SECItem *item, int level)
|
|
{
|
|
secuPBEParams params;
|
|
PRArenaPool *arena = NULL;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(NULL);
|
|
|
|
/* allocate an arena to use */
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
set_nspr_error(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PORT_Memset(¶ms, 0, sizeof params);
|
|
|
|
if (SEC_QuickDERDecodeItem(arena, ¶ms, secuPBEParamsTemp, item) != SECSuccess) {
|
|
goto fail;
|
|
}
|
|
|
|
obj = secitem_to_pystr_hex(¶ms.salt);
|
|
FMT_OBJ_AND_APPEND(lines, _("Salt"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
obj = integer_secitem_to_pystr(¶ms.iterationCount);
|
|
FMT_OBJ_AND_APPEND(lines, _("Iteration Count"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
AlgorithmID_get_id_oid(AlgorithmID *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_id);
|
|
return self->py_id;
|
|
}
|
|
|
|
static PyObject *
|
|
AlgorithmID_get_id_tag(AlgorithmID *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return oid_secitem_to_pyint_tag(&self->id.algorithm);
|
|
}
|
|
|
|
static PyObject *
|
|
AlgorithmID_get_id_str(AlgorithmID *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return oid_secitem_to_pystr_desc(&self->id.algorithm);
|
|
}
|
|
|
|
static PyObject *
|
|
AlgorithmID_get_parameters(AlgorithmID *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_parameters);
|
|
return self->py_parameters;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef AlgorithmID_getseters[] = {
|
|
{"id_oid", (getter)AlgorithmID_get_id_oid, (setter)NULL, "algorithm id OID as SecItem", NULL},
|
|
{"id_tag", (getter)AlgorithmID_get_id_tag, (setter)NULL, "algorithm id TAG as a enumerated constant (e.g. tag)", NULL},
|
|
{"id_str", (getter)AlgorithmID_get_id_str, (setter)NULL, "algorithm id as string description", NULL},
|
|
{"parameters", (getter)AlgorithmID_get_parameters, (setter)NULL, "algorithm parameters as SecItem", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef AlgorithmID_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
AlgorithmID_format_lines(AlgorithmID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
SECOidTag alg_tag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
obj = oid_secitem_to_pystr_desc(&self->id.algorithm);
|
|
FMT_OBJ_AND_APPEND(lines, _("Algorithm"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
alg_tag = SECOID_GetAlgorithmTag(&self->id);
|
|
if (SEC_PKCS5IsAlgorithmPBEAlgTag(alg_tag)) {
|
|
switch (alg_tag) {
|
|
case SEC_OID_PKCS5_PBKDF2:
|
|
FMT_LABEL_AND_APPEND(lines, _("Parameters"), level, fail);
|
|
obj = KDF2Params_format_lines(&self->id.parameters, level+1);
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj, fail);
|
|
break;
|
|
case SEC_OID_PKCS5_PBES2:
|
|
FMT_LABEL_AND_APPEND(lines, _("Encryption"), level, fail);
|
|
obj = PKCS5V2Params_format_lines(&self->id.parameters, level+1);
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj, fail);
|
|
break;
|
|
case SEC_OID_PKCS5_PBMAC1:
|
|
FMT_LABEL_AND_APPEND(lines, _("MAC"), level, fail);
|
|
obj = PKCS5V2Params_format_lines(&self->id.parameters, level+1);
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj, fail);
|
|
break;
|
|
default:
|
|
FMT_LABEL_AND_APPEND(lines, _("Parameters"), level, fail);
|
|
obj = PBEParams_format_lines(&self->id.parameters, level+1);
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj, fail);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_RSA_PSS
|
|
if (alg_tag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Parameters"), level, fail);
|
|
obj = RSAPSSParams_format_lines(&self->id.parameters, level+1);
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj, fail);
|
|
}
|
|
#endif
|
|
|
|
if ((self->id.parameters.len == 0) ||
|
|
(self->id.parameters.len == 2 && memcmp(self->id.parameters.data, "\005\000", 2) == 0)) {
|
|
/* No arguments or NULL argument */
|
|
} else {
|
|
/* Print args to algorithm */
|
|
PyObject *hex_lines = NULL;
|
|
|
|
if ((hex_lines = raw_data_to_hex(self->id.parameters.data, self->id.parameters.len,
|
|
OCTETS_PER_LINE_DEFAULT, HEX_SEPARATOR_DEFAULT)) != NULL) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Raw Parameter Data"), level, fail);
|
|
APPEND_LINES_AND_CLEAR(lines, hex_lines, level+1, fail);
|
|
}
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
AlgorithmID_format(AlgorithmID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)AlgorithmID_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
AlgorithmID_str(AlgorithmID *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = AlgorithmID_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef AlgorithmID_methods[] = {
|
|
{"format_lines", (PyCFunction)AlgorithmID_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)AlgorithmID_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
AlgorithmID_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
AlgorithmID *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (AlgorithmID *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(&self->id, 0, sizeof(self->id));
|
|
self->py_id = NULL;
|
|
self->py_parameters = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
AlgorithmID_traverse(AlgorithmID *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_id);
|
|
Py_VISIT(self->py_parameters);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
AlgorithmID_clear(AlgorithmID* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_id);
|
|
Py_CLEAR(self->py_parameters);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
AlgorithmID_dealloc(AlgorithmID* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
AlgorithmID_clear(self);
|
|
SECOID_DestroyAlgorithmID(&self->id, PR_FALSE);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(AlgorithmID_doc,
|
|
"An object representing a signature algorithm");
|
|
|
|
static int
|
|
AlgorithmID_init(AlgorithmID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
AlgorithmID_repr(AlgorithmID *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject AlgorithmIDType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.AlgorithmID", /* tp_name */
|
|
sizeof(AlgorithmID), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)AlgorithmID_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)AlgorithmID_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)AlgorithmID_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
AlgorithmID_doc, /* tp_doc */
|
|
(traverseproc)AlgorithmID_traverse, /* tp_traverse */
|
|
(inquiry)AlgorithmID_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
AlgorithmID_methods, /* tp_methods */
|
|
AlgorithmID_members, /* tp_members */
|
|
AlgorithmID_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)AlgorithmID_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
AlgorithmID_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
AlgorithmID_new_from_SECAlgorithmID(SECAlgorithmID *id)
|
|
{
|
|
AlgorithmID *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (AlgorithmID *) AlgorithmIDType.tp_new(&AlgorithmIDType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (SECOID_CopyAlgorithmID(NULL, &self->id, id) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_id = SecItem_new_from_SECItem(&id->algorithm, SECITEM_algorithm)) == NULL) {
|
|
SECOID_DestroyAlgorithmID(&self->id, PR_FALSE);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_parameters = SecItem_new_from_SECItem(&id->parameters, SECITEM_unknown)) == NULL) {
|
|
SECOID_DestroyAlgorithmID(&self->id, PR_FALSE);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =========================== RSAGenParams Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
RSAGenParams_get_key_size(RSAGenParams *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->params.keySizeInBits);
|
|
|
|
}
|
|
|
|
static int
|
|
RSAGenParams_set_key_size(RSAGenParams *self, PyObject *value, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the key_size attribute");
|
|
return -1;
|
|
}
|
|
|
|
if (!PyInt_Check(value)) {
|
|
PyErr_Format(PyExc_TypeError, "key_size must be a integer, not %.200s",
|
|
Py_TYPE(value)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
self->params.keySizeInBits = PyInt_AsLong(value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
RSAGenParams_get_public_exponent(RSAGenParams *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->params.keySizeInBits);
|
|
|
|
}
|
|
|
|
static int
|
|
RSAGenParams_set_public_exponent(RSAGenParams *self, PyObject *value, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the public_exponent attribute");
|
|
return -1;
|
|
}
|
|
|
|
if (!PyInt_Check(value)) {
|
|
PyErr_Format(PyExc_TypeError, "public_exponent must be a integer, not %.200s",
|
|
Py_TYPE(value)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
self->params.pe = PyInt_AsLong(value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef RSAGenParams_getseters[] = {
|
|
{"key_size", (getter)RSAGenParams_get_key_size, (setter)RSAGenParams_set_key_size,
|
|
"key size in bits (integer)", NULL},
|
|
{"public_exponent", (getter)RSAGenParams_get_public_exponent, (setter)RSAGenParams_set_public_exponent,
|
|
"public exponent (integer)", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef RSAGenParams_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyMethodDef RSAGenParams_methods[] = {
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
RSAGenParams_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
RSAGenParams *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (RSAGenParams *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(&self->params, 0, sizeof(self->params));
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
RSAGenParams_dealloc(RSAGenParams* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(RSAGenParams_doc,
|
|
"RSAGenParams(key_size=1024, public_exponent=0x10001)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
key_size : integer\n\
|
|
RSA key size in bits.\n\
|
|
public_exponent : integer\n\
|
|
public exponent.\n\
|
|
\n\
|
|
An object representing RSAGenParams.\n\
|
|
");
|
|
|
|
static int
|
|
RSAGenParams_init(RSAGenParams *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"key_size", "exponent", NULL};
|
|
int key_size = 1024;
|
|
unsigned long public_exponent = 0x10001;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ik:RSAGenParams", kwlist,
|
|
&key_size, &public_exponent))
|
|
return -1;
|
|
|
|
self->params.keySizeInBits = key_size;
|
|
self->params.pe = public_exponent;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
RSAGenParams_str(RSAGenParams *self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyString_FromFormat("key_size=%d public_exponent=%lu",
|
|
self->params.keySizeInBits,
|
|
self->params.pe);
|
|
}
|
|
|
|
static PyTypeObject RSAGenParamsType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.RSAGenParams", /* tp_name */
|
|
sizeof(RSAGenParams), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)RSAGenParams_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)RSAGenParams_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
RSAGenParams_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
RSAGenParams_methods, /* tp_methods */
|
|
RSAGenParams_members, /* tp_members */
|
|
RSAGenParams_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)RSAGenParams_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
RSAGenParams_new, /* tp_new */
|
|
};
|
|
|
|
/* ========================================================================== */
|
|
/* ============================ KEYPQGParams Class ========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
KEYPQGParams_get_prime(KEYPQGParams *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SecItem_new_from_SECItem(&self->params.prime, SECITEM_unknown);
|
|
}
|
|
|
|
static PyObject *
|
|
KEYPQGParams_get_subprime(KEYPQGParams *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SecItem_new_from_SECItem(&self->params.subPrime, SECITEM_unknown);
|
|
}
|
|
|
|
static PyObject *
|
|
KEYPQGParams_get_base(KEYPQGParams *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SecItem_new_from_SECItem(&self->params.base, SECITEM_unknown);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef KEYPQGParams_getseters[] = {
|
|
{"prime", (getter)KEYPQGParams_get_prime, (setter)NULL, "key prime value, also known as p", NULL},
|
|
{"subprime", (getter)KEYPQGParams_get_subprime, (setter)NULL, "key subprime value, also known as q", NULL},
|
|
{"base", (getter)KEYPQGParams_get_base, (setter)NULL, "key base value, also known as g", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef KEYPQGParams_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyObject *
|
|
KEYPQGParams_format_lines(KEYPQGParams *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj_lines = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if ((obj = KEYPQGParams_get_prime(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(lines, _("Prime"), obj, level, fail);
|
|
|
|
if ((obj = KEYPQGParams_get_subprime(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(lines, _("SubPrime"), obj, level, fail);
|
|
|
|
if ((obj = KEYPQGParams_get_base(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(lines, _("Base"), obj, level, fail);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj_lines);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
KEYPQGParams_format(KEYPQGParams *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)KEYPQGParams_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
KEYPQGParams_str(KEYPQGParams *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = KEYPQGParams_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef KEYPQGParams_methods[] = {
|
|
{"format_lines", (PyCFunction)KEYPQGParams_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)KEYPQGParams_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
KEYPQGParams_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
KEYPQGParams *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (KEYPQGParams *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(&self->params, 0, sizeof(self->params));
|
|
|
|
if ((self->params.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
KEYPQGParams_dealloc(KEYPQGParams* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.arena) {
|
|
PORT_FreeArena(self->params.arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(KEYPQGParams_doc,
|
|
"KEYPQGParams(prime=None, subprime=None, base=None)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
prime : SecItem or str or any buffer compatible object or None\n\
|
|
prime (also known as p)\n\
|
|
subprime : SecItem or str or any buffer compatible object or None\n\
|
|
subprime (also known as q)\n\
|
|
base : SecItem or str or any buffer compatible object or None\n\
|
|
base (also known as g)\n\
|
|
\n\
|
|
An object representing DSA key parameters\n\
|
|
- prime (also known as p)\n\
|
|
- subprime (also known as q)\n\
|
|
- base (also known as g)\n\
|
|
\n\
|
|
If no parameters are passed the default PQG the KeyPQGParams will\n\
|
|
be intialized to default values. If you pass any initialization\n\
|
|
parameters then they must all be passed.\n\
|
|
");
|
|
|
|
static int
|
|
KEYPQGParams_init(KEYPQGParams *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
PyObject *py_prime = NULL;
|
|
SECItem prime_tmp_item;
|
|
SECItem *prime_item = NULL;
|
|
|
|
PyObject *py_subprime = NULL;
|
|
SECItem subprime_tmp_item;
|
|
SECItem *subprime_item = NULL;
|
|
|
|
PyObject *py_base = NULL;
|
|
SECItem base_tmp_item;
|
|
SECItem *base_item = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
// FIXME: prime, subprime & base are really large ASN.1 integers
|
|
// we should accept a python int or python long and convert to a SecItem
|
|
|
|
SECITEM_PARAM(py_prime, prime_item, prime_tmp_item, false, "prime");
|
|
SECITEM_PARAM(py_subprime, subprime_item, subprime_tmp_item, false, "subprime");
|
|
SECITEM_PARAM(py_base, base_item, base_tmp_item, false, "base");
|
|
|
|
if (py_prime == NULL && py_subprime == NULL && py_base == NULL) {
|
|
if ((KEYPQGParams_init_from_SECKEYPQGParams(self, &default_pqg_params)) == NULL) {
|
|
return -1;
|
|
}
|
|
} else if (py_prime != NULL && py_subprime != NULL && py_base != NULL) {
|
|
SECKEYPQGParams params;
|
|
|
|
params.arena = NULL;
|
|
params.prime = *prime_item;
|
|
params.subPrime = *subprime_item;
|
|
params.base = *base_item;
|
|
|
|
if ((KEYPQGParams_init_from_SECKEYPQGParams(self, ¶ms)) == NULL) {
|
|
return -1;
|
|
}
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError, "prime, subprime and base must all be provided or none of them provided, not a mix");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
KEYPQGParams_repr(KEYPQGParams *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject KEYPQGParamsType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.KEYPQGParams", /* tp_name */
|
|
sizeof(KEYPQGParams), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)KEYPQGParams_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)KEYPQGParams_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)KEYPQGParams_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
KEYPQGParams_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
KEYPQGParams_methods, /* tp_methods */
|
|
KEYPQGParams_members, /* tp_members */
|
|
KEYPQGParams_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)KEYPQGParams_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
KEYPQGParams_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
KEYPQGParams_init_from_SECKEYPQGParams(KEYPQGParams *self, const SECKEYPQGParams *params)
|
|
{
|
|
|
|
SECITEM_FreeItem(&self->params.prime, PR_FALSE);
|
|
if (SECITEM_CopyItem(self->params.arena, &self->params.prime, ¶ms->prime) != SECSuccess) {
|
|
return NULL;
|
|
}
|
|
|
|
SECITEM_FreeItem(&self->params.subPrime, PR_FALSE);
|
|
if (SECITEM_CopyItem(self->params.arena, &self->params.subPrime, ¶ms->subPrime) != SECSuccess) {
|
|
return NULL;
|
|
}
|
|
|
|
SECITEM_FreeItem(&self->params.base, PR_FALSE);
|
|
if (SECITEM_CopyItem(self->params.arena, &self->params.base, ¶ms->base) != SECSuccess) {
|
|
return NULL;
|
|
}
|
|
|
|
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
PyObject *
|
|
KEYPQGParams_new_from_SECKEYPQGParams(const SECKEYPQGParams *params)
|
|
{
|
|
KEYPQGParams *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (KEYPQGParams *) KEYPQGParamsType.tp_new(&KEYPQGParamsType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((KEYPQGParams_init_from_SECKEYPQGParams(self, params) == NULL)) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =========================== RSAPublicKey Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
RSAPublicKey_get_modulus(RSAPublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_modulus);
|
|
return self->py_modulus;
|
|
}
|
|
|
|
static PyObject *
|
|
RSAPublicKey_get_exponent(RSAPublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_exponent);
|
|
return self->py_exponent;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef RSAPublicKey_getseters[] = {
|
|
{"modulus", (getter)RSAPublicKey_get_modulus, (setter)NULL, "RSA modulus", NULL},
|
|
{"exponent", (getter)RSAPublicKey_get_exponent, (setter)NULL, "RSA exponent", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef RSAPublicKey_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
RSAPublicKey_format_lines(RSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((obj = RSAPublicKey_get_modulus(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(lines, _("Modulus"), obj, level, fail);
|
|
|
|
if ((obj = RSAPublicKey_get_exponent(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(lines, _("Exponent"), obj, level, fail);
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
RSAPublicKey_format(RSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)RSAPublicKey_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
RSAPublicKey_str(RSAPublicKey *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = RSAPublicKey_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef RSAPublicKey_methods[] = {
|
|
{"format_lines", (PyCFunction)RSAPublicKey_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)RSAPublicKey_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
RSAPublicKey_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
RSAPublicKey *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (RSAPublicKey *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_modulus = NULL;
|
|
self->py_exponent = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
RSAPublicKey_traverse(RSAPublicKey *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_modulus);
|
|
Py_VISIT(self->py_exponent);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
RSAPublicKey_clear(RSAPublicKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_modulus);
|
|
Py_CLEAR(self->py_exponent);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
RSAPublicKey_dealloc(RSAPublicKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
RSAPublicKey_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(RSAPublicKey_doc,
|
|
"An object representing an RSA Public Key");
|
|
|
|
static int
|
|
RSAPublicKey_init(RSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
RSAPublicKey_repr(RSAPublicKey *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject RSAPublicKeyType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.RSAPublicKey", /* tp_name */
|
|
sizeof(RSAPublicKey), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)RSAPublicKey_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)RSAPublicKey_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)RSAPublicKey_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
RSAPublicKey_doc, /* tp_doc */
|
|
(traverseproc)RSAPublicKey_traverse, /* tp_traverse */
|
|
(inquiry)RSAPublicKey_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
RSAPublicKey_methods, /* tp_methods */
|
|
RSAPublicKey_members, /* tp_members */
|
|
RSAPublicKey_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)RSAPublicKey_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
RSAPublicKey_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
RSAPublicKey_new_from_SECKEYRSAPublicKey(SECKEYRSAPublicKey *rsa)
|
|
{
|
|
RSAPublicKey *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (RSAPublicKey *) RSAPublicKeyType.tp_new(&RSAPublicKeyType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_modulus = SecItem_new_from_SECItem(&rsa->modulus, SECITEM_unknown)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_exponent = SecItem_new_from_SECItem(&rsa->publicExponent, SECITEM_unknown)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =========================== DSAPublicKey Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
DSAPublicKey_get_pqg_params(DSAPublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_pqg_params);
|
|
return self->py_pqg_params;
|
|
}
|
|
|
|
static PyObject *
|
|
DSAPublicKey_get_public_value(DSAPublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_public_value);
|
|
return self->py_public_value;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef DSAPublicKey_getseters[] = {
|
|
{"pqg_params", (getter)DSAPublicKey_get_pqg_params, (setter)NULL, "DSA P,Q,G params as a KEYPQGParams object", NULL},
|
|
{"public_value", (getter)DSAPublicKey_get_public_value, (setter)NULL, "DSA public_value", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef DSAPublicKey_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
DSAPublicKey_format_lines(DSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *exponent = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((obj = DSAPublicKey_get_pqg_params(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = DSAPublicKey_get_public_value(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_SEC_INT_OBJ_APPEND_AND_CLEAR(lines, _("Public Value"), obj, level, fail);
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(exponent);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
DSAPublicKey_format(DSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)DSAPublicKey_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
DSAPublicKey_str(DSAPublicKey *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = DSAPublicKey_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef DSAPublicKey_methods[] = {
|
|
{"format_lines", (PyCFunction)DSAPublicKey_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)DSAPublicKey_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
DSAPublicKey_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
DSAPublicKey *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (DSAPublicKey *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_pqg_params = NULL;
|
|
self->py_public_value = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
DSAPublicKey_traverse(DSAPublicKey *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_pqg_params);
|
|
Py_VISIT(self->py_public_value);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
DSAPublicKey_clear(DSAPublicKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_pqg_params);
|
|
Py_CLEAR(self->py_public_value);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
DSAPublicKey_dealloc(DSAPublicKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
DSAPublicKey_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(DSAPublicKey_doc,
|
|
"A object representing a DSA Public Key");
|
|
|
|
static int
|
|
DSAPublicKey_init(DSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
DSAPublicKey_repr(DSAPublicKey *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject DSAPublicKeyType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.DSAPublicKey", /* tp_name */
|
|
sizeof(DSAPublicKey), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)DSAPublicKey_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)DSAPublicKey_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)DSAPublicKey_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
DSAPublicKey_doc, /* tp_doc */
|
|
(traverseproc)DSAPublicKey_traverse, /* tp_traverse */
|
|
(inquiry)DSAPublicKey_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
DSAPublicKey_methods, /* tp_methods */
|
|
DSAPublicKey_members, /* tp_members */
|
|
DSAPublicKey_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)DSAPublicKey_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
DSAPublicKey_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
DSAPublicKey_new_from_SECKEYDSAPublicKey(SECKEYDSAPublicKey *dsa)
|
|
{
|
|
DSAPublicKey *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (DSAPublicKey *) DSAPublicKeyType.tp_new(&DSAPublicKeyType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_pqg_params = KEYPQGParams_new_from_SECKEYPQGParams(&dsa->params)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_public_value = SecItem_new_from_SECItem(&dsa->publicValue, SECITEM_unknown)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================= SignedData Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
SignedData_get_der(SignedData *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_der);
|
|
return self->py_der;
|
|
}
|
|
|
|
static PyObject *
|
|
SignedData_get_data(SignedData *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_data);
|
|
return self->py_data;
|
|
}
|
|
|
|
static PyObject *
|
|
SignedData_get_algorithm(SignedData *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_algorithm);
|
|
return self->py_algorithm;
|
|
}
|
|
|
|
static PyObject *
|
|
SignedData_get_signature(SignedData *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_signature);
|
|
return self->py_signature;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef SignedData_getseters[] = {
|
|
{"der", (getter)SignedData_get_der, (setter)NULL, "original der encoded ASN1 signed data as a SecItem object", NULL},
|
|
{"data", (getter)SignedData_get_data, (setter)NULL, "signed data as a SecItem object", NULL},
|
|
{"algorithm", (getter)SignedData_get_algorithm, (setter)NULL, "signature algorithm as a AlgorithmID object", NULL},
|
|
{"signature", (getter)SignedData_get_signature, (setter)NULL, "signature as a SecItem object", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef SignedData_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
SignedData_format_lines(SignedData *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((obj = SignedData_get_algorithm(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_LABEL_AND_APPEND(lines, _("Signature Algorithm"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Signature"), level, fail);
|
|
|
|
if ((obj = SignedData_get_signature(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_OBJ_TO_HEX_LINES_AND_CLEAR(lines, obj, level+1, fail);
|
|
|
|
obj = fingerprint_format_lines(&((SecItem *)self->py_der)->item, level);
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj, fail);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
SignedData_format(SignedData *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)SignedData_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
SignedData_str(SignedData *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
py_formatted_result = SignedData_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef SignedData_methods[] = {
|
|
{"format_lines", (PyCFunction)SignedData_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)SignedData_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
SignedData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
SignedData *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (SignedData *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_der = NULL;
|
|
self->py_data = NULL;
|
|
self->py_algorithm = NULL;
|
|
self->py_signature = NULL;
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
memset(&self->signed_data, 0, sizeof(self->signed_data));
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
SignedData_traverse(SignedData *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_der);
|
|
Py_VISIT(self->py_data);
|
|
Py_VISIT(self->py_algorithm);
|
|
Py_VISIT(self->py_signature);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
SignedData_clear(SignedData* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_der);
|
|
Py_CLEAR(self->py_data);
|
|
Py_CLEAR(self->py_algorithm);
|
|
Py_CLEAR(self->py_signature);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
SignedData_dealloc(SignedData* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
SignedData_clear(self);
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(SignedData_doc,
|
|
"A object representing a signature");
|
|
|
|
static int
|
|
SignedData_init(SignedData *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
SignedData_repr(SignedData *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject SignedDataType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.SignedData", /* tp_name */
|
|
sizeof(SignedData), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)SignedData_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)SignedData_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)SignedData_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
SignedData_doc, /* tp_doc */
|
|
(traverseproc)SignedData_traverse, /* tp_traverse */
|
|
(inquiry)SignedData_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
SignedData_methods, /* tp_methods */
|
|
SignedData_members, /* tp_members */
|
|
SignedData_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)SignedData_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
SignedData_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
SignedData_new_from_SECItem(SECItem *item)
|
|
{
|
|
SignedData *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (SignedData *) SignedDataType.tp_new(&SignedDataType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (SEC_ASN1DecodeItem(self->arena, &self->signed_data,
|
|
SEC_ASN1_GET(CERT_SignedDataTemplate), item) != SECSuccess) {
|
|
set_nspr_error("cannot decode DER encoded signed data");
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_der =
|
|
SecItem_new_from_SECItem(item, SECITEM_signed_data)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_data =
|
|
SecItem_new_from_SECItem(&self->signed_data.data, SECITEM_unknown)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_algorithm =
|
|
AlgorithmID_new_from_SECAlgorithmID(&self->signed_data.signatureAlgorithm)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
DER_ConvertBitString(&self->signed_data.signature);
|
|
if ((self->py_signature =
|
|
SecItem_new_from_SECItem(&self->signed_data.signature, SECITEM_signature)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================= PublicKey Class ============================ */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
PublicKey_get_key_type(PublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->pk->keyType);
|
|
}
|
|
|
|
static PyObject *
|
|
PublicKey_get_key_type_str(PublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyString_FromString(key_type_str(self->pk->keyType));
|
|
}
|
|
|
|
static PyObject *
|
|
PublicKey_get_rsa(PublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->pk->keyType == rsaKey) {
|
|
Py_INCREF(self->py_rsa_key);
|
|
return self->py_rsa_key;
|
|
} else {
|
|
PyErr_Format(PyExc_AttributeError, "when '%.50s' object has key_type=%s there is no attribute 'rsa'",
|
|
Py_TYPE(self)->tp_name, key_type_str(self->pk->keyType));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static PyObject *
|
|
PublicKey_get_dsa(PublicKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->pk->keyType == dsaKey) {
|
|
Py_INCREF(self->py_dsa_key);
|
|
return self->py_dsa_key;
|
|
} else {
|
|
PyErr_Format(PyExc_AttributeError, "when '%.50s' object has key_type=%s there is no attribute 'dsa'",
|
|
Py_TYPE(self)->tp_name, key_type_str(self->pk->keyType));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static
|
|
PyGetSetDef PublicKey_getseters[] = {
|
|
{"key_type", (getter)PublicKey_get_key_type, (setter)NULL, "key type (e.g. rsaKey, dsaKey, etc.) as an int", NULL},
|
|
{"key_type_str", (getter)PublicKey_get_key_type_str, (setter)NULL, "key type as a string", NULL},
|
|
{"rsa", (getter)PublicKey_get_rsa, (setter)NULL, "RSA key as a RSAPublicKey object", NULL},
|
|
{"dsa", (getter)PublicKey_get_dsa, (setter)NULL, "RSA key as a RSAPublicKey object", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PublicKey_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
PublicKey_format_lines(PublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *py_key = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
switch(self->pk->keyType) { /* FIXME: handle the other cases */
|
|
case rsaKey:
|
|
FMT_LABEL_AND_APPEND(lines, _("RSA Public Key"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, self->py_rsa_key, level+1, fail);
|
|
break;
|
|
case dsaKey:
|
|
FMT_LABEL_AND_APPEND(lines, _("DSA Public Key"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, self->py_dsa_key, level+1, fail);
|
|
break;
|
|
case fortezzaKey:
|
|
case dhKey:
|
|
case keaKey:
|
|
case ecKey:
|
|
case rsaPssKey:
|
|
case rsaOaepKey:
|
|
case nullKey:
|
|
if ((obj = PublicKey_get_key_type_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Key Type"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
break;
|
|
}
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(lines);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(py_key);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
PublicKey_format(PublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)PublicKey_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
PublicKey_str(PublicKey *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
py_formatted_result = PublicKey_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef PublicKey_methods[] = {
|
|
{"format_lines", (PyCFunction)PublicKey_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)PublicKey_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
PublicKey_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
PublicKey *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (PublicKey *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_rsa_key = NULL;
|
|
self->py_dsa_key = NULL;
|
|
|
|
memset(&self->pk, 0, sizeof(self->pk));
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
PublicKey_traverse(PublicKey *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_rsa_key);
|
|
Py_VISIT(self->py_dsa_key);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
PublicKey_clear(PublicKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_rsa_key);
|
|
Py_CLEAR(self->py_dsa_key);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
PublicKey_dealloc(PublicKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
PublicKey_clear(self);
|
|
SECKEY_DestroyPublicKey(self->pk);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PublicKey_doc,
|
|
"An object representing a Public Key");
|
|
|
|
static int
|
|
PublicKey_init(PublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
PublicKey_repr(PublicKey *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject PublicKeyType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PublicKey", /* tp_name */
|
|
sizeof(PublicKey), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PublicKey_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)PublicKey_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)PublicKey_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
PublicKey_doc, /* tp_doc */
|
|
(traverseproc)PublicKey_traverse, /* tp_traverse */
|
|
(inquiry)PublicKey_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PublicKey_methods, /* tp_methods */
|
|
PublicKey_members, /* tp_members */
|
|
PublicKey_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PublicKey_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PublicKey_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
PublicKey_new_from_SECKEYPublicKey(SECKEYPublicKey *pk)
|
|
{
|
|
PublicKey *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (PublicKey *) PublicKeyType.tp_new(&PublicKeyType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->pk = pk;
|
|
|
|
switch(pk->keyType) { /* FIXME: handle the other cases */
|
|
case rsaKey:
|
|
if ((self->py_rsa_key = RSAPublicKey_new_from_SECKEYRSAPublicKey(&pk->u.rsa)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
break;
|
|
case dsaKey:
|
|
if ((self->py_dsa_key = DSAPublicKey_new_from_SECKEYDSAPublicKey(&pk->u.dsa)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
break;
|
|
case fortezzaKey:
|
|
case dhKey:
|
|
case keaKey:
|
|
case ecKey:
|
|
case rsaPssKey:
|
|
case rsaOaepKey:
|
|
case nullKey:
|
|
break;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ======================= SubjectPublicKeyInfo Class ======================= */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_get_algorithm(SubjectPublicKeyInfo *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_algorithm);
|
|
return self->py_algorithm;
|
|
}
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_get_public_key(SubjectPublicKeyInfo *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_public_key);
|
|
return self->py_public_key;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef SubjectPublicKeyInfo_getseters[] = {
|
|
{"algorithm", (getter)SubjectPublicKeyInfo_get_algorithm, (setter)NULL, "algorithm", NULL},
|
|
{"public_key", (getter)SubjectPublicKeyInfo_get_public_key, (setter)NULL, "PublicKey object", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef SubjectPublicKeyInfo_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_format_lines(SubjectPublicKeyInfo *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *py_public_key = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((obj = SubjectPublicKeyInfo_get_algorithm(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_LABEL_AND_APPEND(lines, _("Public Key Algorithm"), level, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((py_public_key = SubjectPublicKeyInfo_get_public_key(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, py_public_key, level, fail);
|
|
Py_CLEAR(py_public_key);
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(lines);
|
|
Py_XDECREF(py_public_key);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_format(SubjectPublicKeyInfo *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)SubjectPublicKeyInfo_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_str(SubjectPublicKeyInfo *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
py_formatted_result = SubjectPublicKeyInfo_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef SubjectPublicKeyInfo_methods[] = {
|
|
{"format_lines", (PyCFunction)SubjectPublicKeyInfo_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)SubjectPublicKeyInfo_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
SubjectPublicKeyInfo *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (SubjectPublicKeyInfo *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_algorithm = NULL;
|
|
self->py_public_key = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
SubjectPublicKeyInfo_traverse(SubjectPublicKeyInfo *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_algorithm);
|
|
Py_VISIT(self->py_public_key);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
SubjectPublicKeyInfo_clear(SubjectPublicKeyInfo* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
DumpRefCount(self->py_public_key);
|
|
Py_CLEAR(self->py_algorithm);
|
|
Py_CLEAR(self->py_public_key);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
SubjectPublicKeyInfo_dealloc(SubjectPublicKeyInfo* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
SubjectPublicKeyInfo_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(SubjectPublicKeyInfo_doc,
|
|
"An object representing a Subject Public Key");
|
|
|
|
static int
|
|
SubjectPublicKeyInfo_init(SubjectPublicKeyInfo *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
SubjectPublicKeyInfo_repr(SubjectPublicKeyInfo *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject SubjectPublicKeyInfoType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.SubjectPublicKeyInfo", /* tp_name */
|
|
sizeof(SubjectPublicKeyInfo), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)SubjectPublicKeyInfo_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)SubjectPublicKeyInfo_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)SubjectPublicKeyInfo_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
SubjectPublicKeyInfo_doc, /* tp_doc */
|
|
(traverseproc)SubjectPublicKeyInfo_traverse, /* tp_traverse */
|
|
(inquiry)SubjectPublicKeyInfo_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
SubjectPublicKeyInfo_methods, /* tp_methods */
|
|
SubjectPublicKeyInfo_members, /* tp_members */
|
|
SubjectPublicKeyInfo_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)SubjectPublicKeyInfo_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
SubjectPublicKeyInfo_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
SubjectPublicKeyInfo_new_from_CERTSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
|
|
{
|
|
SubjectPublicKeyInfo *self = NULL;
|
|
SECKEYPublicKey *pk = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (SubjectPublicKeyInfo *) SubjectPublicKeyInfoType.tp_new(&SubjectPublicKeyInfoType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_algorithm = AlgorithmID_new_from_SECAlgorithmID(&spki->algorithm)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((pk = SECKEY_ExtractPublicKey(spki)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_public_key = PublicKey_new_from_SECKEYPublicKey(pk)) == NULL) {
|
|
SECKEY_DestroyPublicKey(pk);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
DumpRefCount(self->py_public_key);
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ============================== Utilities ============================= */
|
|
|
|
static CERTDistNames *
|
|
cert_distnames_as_CERTDistNames(PyObject *py_distnames)
|
|
{
|
|
PRArenaPool *arena = NULL;
|
|
CERTDistNames *names = NULL;
|
|
int i;
|
|
SecItem *py_sec_item;
|
|
|
|
if (!(PyList_Check(py_distnames) || PyTuple_Check(py_distnames))) {
|
|
PyErr_SetString(PyExc_TypeError, "cert distnames must be a list or tuple");
|
|
return NULL;
|
|
}
|
|
|
|
/* allocate an arena to use */
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
set_nspr_error(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
/* allocate the header structure */
|
|
if ((names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames))) == NULL) {
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
/* initialize the header struct */
|
|
names->arena = arena;
|
|
names->head = NULL;
|
|
names->nnames = PySequence_Size(py_distnames);
|
|
names->names = NULL;
|
|
|
|
/* construct the array from the list */
|
|
if (names->nnames) {
|
|
names->names = (SECItem *)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
|
|
|
|
if (names->names == NULL) {
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < names->nnames; i++) {
|
|
py_sec_item = (SecItem *)PySequence_GetItem(py_distnames, i); /* new reference */
|
|
if ((!PySecItem_Check(py_sec_item)) || (py_sec_item->kind != SECITEM_dist_name)) {
|
|
PyErr_Format(PyExc_TypeError, "item must be a %s containing a DistName",
|
|
SecItemType.tp_name);
|
|
Py_DECREF(py_sec_item);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
if (SECITEM_CopyItem(arena, &names->names[i], &py_sec_item->item) != SECSuccess) {
|
|
Py_DECREF(py_sec_item);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(py_sec_item);
|
|
}
|
|
}
|
|
return names;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =============================== CertDB Class ============================= */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef CertDB_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CertDB_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(CertDB_find_crl_by_name_doc,
|
|
"find_crl_by_name(name, type=SEC_CRL_TYPE) -> SignedCRL object\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
name to lookup\n\
|
|
type : int\n\
|
|
revocation list type\n\
|
|
\n\
|
|
may be one of:\n\
|
|
- SEC_CRL_TYPE\n\
|
|
- SEC_KRL_TYPE\n\
|
|
\n\
|
|
Returns a SignedCRL object found in the database given a name and revocation list type.\n\
|
|
"
|
|
);
|
|
static PyObject *
|
|
CertDB_find_crl_by_name(CertDB *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"name", "type", NULL};
|
|
char *name;
|
|
int type = SEC_CRL_TYPE;
|
|
CERTName *cert_name;
|
|
SECItem *der_name;
|
|
CERTSignedCrl *signed_crl;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:find_crl_by_name", kwlist,
|
|
&name, &type))
|
|
return NULL;
|
|
|
|
if ((cert_name = CERT_AsciiToName(name)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((der_name = SEC_ASN1EncodeItem (NULL, NULL, (void *)cert_name,
|
|
SEC_ASN1_GET(CERT_NameTemplate))) == NULL) {
|
|
CERT_DestroyName(cert_name);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
CERT_DestroyName(cert_name);
|
|
|
|
if ((signed_crl = SEC_FindCrlByName(self->handle, der_name, type)) == NULL) {
|
|
SECITEM_FreeItem(der_name, PR_TRUE);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
SECITEM_FreeItem(der_name, PR_TRUE);
|
|
|
|
return SignedCRL_new_from_CERTSignedCRL(signed_crl);
|
|
}
|
|
|
|
PyDoc_STRVAR(CertDB_find_crl_by_cert_doc,
|
|
"find_crl_by_cert(cert, type=SEC_CRL_TYPE) -> SignedCRL object\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cert : Certificate object\n\
|
|
certificate used to lookup the CRL.\n\
|
|
type : int\n\
|
|
revocation list type\n\
|
|
\n\
|
|
may be one of:\n\
|
|
- SEC_CRL_TYPE\n\
|
|
- SEC_KRL_TYPE\n\
|
|
\n\
|
|
Returns a SignedCRL object found in the database given a certificate and revocation list type.\n\
|
|
"
|
|
);
|
|
static PyObject *
|
|
CertDB_find_crl_by_cert(CertDB *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"cert", "type", NULL};
|
|
int type = SEC_CRL_TYPE;
|
|
Certificate *py_cert = NULL;
|
|
SECItem *der_cert;
|
|
CERTSignedCrl *signed_crl;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|i:find_crl_by_cert", kwlist,
|
|
&CertificateType, &py_cert, &type))
|
|
return NULL;
|
|
|
|
der_cert = &py_cert->cert->derCert;
|
|
if ((signed_crl = SEC_FindCrlByDERCert(self->handle, der_cert, type)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return SignedCRL_new_from_CERTSignedCRL(signed_crl);
|
|
}
|
|
|
|
|
|
static PyMethodDef CertDB_methods[] = {
|
|
{"find_crl_by_name", (PyCFunction)CertDB_find_crl_by_name, METH_VARARGS|METH_KEYWORDS, CertDB_find_crl_by_name_doc},
|
|
{"find_crl_by_cert", (PyCFunction)CertDB_find_crl_by_cert, METH_VARARGS|METH_KEYWORDS, CertDB_find_crl_by_cert_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
CertDB_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CertDB *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CertDB *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
self->handle = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
CertDB_dealloc(CertDB* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CertDB_doc,
|
|
"An object representing a Certificate Database");
|
|
|
|
static int
|
|
CertDB_init(CertDB *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject CertDBType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CertDB", /* tp_name */
|
|
sizeof(CertDB), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CertDB_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
CertDB_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CertDB_methods, /* tp_methods */
|
|
CertDB_members, /* tp_members */
|
|
CertDB_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)CertDB_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CertDB_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
CertDB_new_from_CERTCertDBHandle(CERTCertDBHandle *cert_handle)
|
|
{
|
|
CertDB *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
if ((self = (CertDB *) CertDBType.tp_new(&CertDBType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->handle = cert_handle;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
static PyObject *
|
|
cert_distnames_new_from_CERTDistNames(CERTDistNames *names)
|
|
{
|
|
PyObject *py_distnames = NULL;
|
|
PyObject *py_sec_item = NULL;
|
|
int i, len;
|
|
|
|
len = names->nnames;
|
|
if ((py_distnames = PyTuple_New(len)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i< names->nnames; i++) {
|
|
if ((py_sec_item = SecItem_new_from_SECItem(&names->names[i], SECITEM_dist_name)) == NULL) {
|
|
Py_DECREF(py_distnames);
|
|
return NULL;
|
|
}
|
|
PyTuple_SetItem(py_distnames, i, py_sec_item);
|
|
}
|
|
|
|
return py_distnames;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ======================== CertificateExtension Class ====================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
CertificateExtension_get_name(CertificateExtension *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return oid_secitem_to_pystr_desc(&self->py_oid->item);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_get_critical(CertificateExtension *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyBool_FromLong(self->critical);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_get_oid(CertificateExtension *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_oid);
|
|
return (PyObject *)self->py_oid;
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_get_oid_tag(CertificateExtension *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return oid_secitem_to_pyint_tag(&self->py_oid->item);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_get_value(CertificateExtension *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_value);
|
|
return (PyObject *)self->py_value;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef CertificateExtension_getseters[] = {
|
|
{"name", (getter)CertificateExtension_get_name, (setter)NULL, "name of extension", NULL},
|
|
{"critical", (getter)CertificateExtension_get_critical, (setter)NULL, "extension is critical flag (boolean)", NULL},
|
|
{"oid", (getter)CertificateExtension_get_oid, (setter)NULL, "oid of extension as SecItem", NULL},
|
|
{"oid_tag", (getter)CertificateExtension_get_oid_tag, (setter)NULL, "oid of extension as a enumerated constant (e.g. tag)", NULL},
|
|
{"value", (getter)CertificateExtension_get_value, (setter)NULL, "extension data as SecItem", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CertificateExtension_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
CertificateExtension_str(CertificateExtension *self)
|
|
{
|
|
return oid_secitem_to_pystr_desc(&self->py_oid->item);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_repr(CertificateExtension *self)
|
|
{
|
|
return CertificateExtension_str(self);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_format_lines(CertificateExtension *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
Py_ssize_t len, i;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
SECOidTag oid_tag;
|
|
PyObject *obj_lines = NULL;
|
|
PyObject *tmp_args = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((obj = CertificateExtension_get_name(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Name"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = CertificateExtension_get_critical(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Critical"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
oid_tag = SECOID_FindOIDTag(&self->py_oid->item);
|
|
|
|
switch(oid_tag) {
|
|
case SEC_OID_PKCS12_KEY_USAGE:
|
|
FMT_LABEL_AND_APPEND(lines, _("Usages"), level, fail);
|
|
if ((tmp_args = Py_BuildValue("(O)", self->py_value)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj = cert_x509_key_usage(NULL, tmp_args, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(tmp_args);
|
|
if ((obj_lines = make_line_fmt_tuples(level+1, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj_lines, fail);
|
|
break;
|
|
|
|
case SEC_OID_NS_CERT_EXT_CERT_TYPE:
|
|
FMT_LABEL_AND_APPEND(lines, _("Types"), level, fail);
|
|
if ((tmp_args = Py_BuildValue("(O)", self->py_value)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj = cert_x509_cert_type(NULL, tmp_args, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(tmp_args);
|
|
if ((obj_lines = make_line_fmt_tuples(level+1, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj_lines, fail);
|
|
break;
|
|
|
|
case SEC_OID_X509_SUBJECT_KEY_ID:
|
|
FMT_LABEL_AND_APPEND(lines, _("Data"), level, fail);
|
|
if ((obj_lines = SECItem_der_to_hex(&self->py_value->item,
|
|
OCTETS_PER_LINE_DEFAULT, HEX_SEPARATOR_DEFAULT)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_LINES_AND_CLEAR(lines, obj_lines, level+1, fail);
|
|
break;
|
|
|
|
case SEC_OID_X509_CRL_DIST_POINTS:
|
|
if ((obj = CRLDistributionPts_new_from_SECItem(&self->py_value->item)) == NULL) {
|
|
goto fail;
|
|
}
|
|
len = PyObject_Size(obj);
|
|
if ((obj1 = PyString_FromFormat("CRL Distribution Points: [%d total]", len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj1, level, fail);
|
|
Py_CLEAR(obj1);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if ((obj1 = PyString_FromFormat("Point [%d]:", i+1)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj1, level+1, fail);
|
|
Py_CLEAR(obj1);
|
|
if ((obj1 = PySequence_GetItem(obj, i)) == NULL) {
|
|
goto fail;
|
|
}
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj1, level+2, fail);
|
|
Py_CLEAR(obj1);
|
|
}
|
|
|
|
break;
|
|
|
|
case SEC_OID_X509_AUTH_KEY_ID:
|
|
if ((obj = AuthKeyID_new_from_SECItem(&self->py_value->item)) == NULL) {
|
|
goto fail;
|
|
}
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
break;
|
|
|
|
case SEC_OID_X509_EXT_KEY_USAGE:
|
|
FMT_LABEL_AND_APPEND(lines, _("Usages"), level, fail);
|
|
if ((tmp_args = Py_BuildValue("(O)", self->py_value)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj = cert_x509_ext_key_usage(NULL, tmp_args, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(tmp_args);
|
|
if ((obj_lines = make_line_fmt_tuples(level+1, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj_lines, fail);
|
|
break;
|
|
|
|
case SEC_OID_X509_BASIC_CONSTRAINTS:
|
|
if ((obj = BasicConstraints_new_from_SECItem(&self->py_value->item)) == NULL) {
|
|
goto fail;
|
|
}
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
break;
|
|
|
|
case SEC_OID_X509_SUBJECT_ALT_NAME:
|
|
case SEC_OID_X509_ISSUER_ALT_NAME:
|
|
FMT_LABEL_AND_APPEND(lines, _("Names"), level, fail);
|
|
if ((tmp_args = Py_BuildValue("(O)", self->py_value)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj = cert_x509_alt_name(NULL, tmp_args, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(tmp_args);
|
|
if ((obj_lines = make_line_fmt_tuples(level+1, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_LINE_TUPLES_AND_CLEAR(lines, obj_lines, fail);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(lines);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(obj_lines);
|
|
Py_XDECREF(tmp_args);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateExtension_format(RSAPublicKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)CertificateExtension_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyMethodDef CertificateExtension_methods[] = {
|
|
{"format_lines", (PyCFunction)CertificateExtension_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)CertificateExtension_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
CertificateExtension_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CertificateExtension *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CertificateExtension *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_oid = NULL;
|
|
self->py_value = NULL;
|
|
self->critical = 0;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
CertificateExtension_traverse(CertificateExtension *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_oid);
|
|
Py_VISIT(self->py_value);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
CertificateExtension_clear(CertificateExtension* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_oid);
|
|
Py_CLEAR(self->py_value);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
CertificateExtension_dealloc(CertificateExtension* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
CertificateExtension_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CertificateExtension_doc,
|
|
"An object representing a certificate extension");
|
|
|
|
static int
|
|
CertificateExtension_init(CertificateExtension *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject CertificateExtensionType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CertificateExtension", /* tp_name */
|
|
sizeof(CertificateExtension), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CertificateExtension_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)CertificateExtension_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)CertificateExtension_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
CertificateExtension_doc, /* tp_doc */
|
|
(traverseproc)CertificateExtension_traverse,/* tp_traverse */
|
|
(inquiry)CertificateExtension_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CertificateExtension_methods, /* tp_methods */
|
|
CertificateExtension_members, /* tp_members */
|
|
CertificateExtension_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)CertificateExtension_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CertificateExtension_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
CertificateExtension_new_from_CERTCertExtension(CERTCertExtension *extension)
|
|
{
|
|
CertificateExtension *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
if ((self = (CertificateExtension *) CertificateExtensionType.tp_new(&CertificateExtensionType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_oid = (SecItem *)
|
|
SecItem_new_from_SECItem(&extension->id, SECITEM_cert_extension_oid)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->py_value = (SecItem *)
|
|
SecItem_new_from_SECItem(&extension->value, SECITEM_cert_extension_value)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if (extension->critical.data && extension->critical.len) {
|
|
self->critical = extension->critical.data[0];
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================ Certificate Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
Certificate_get_valid_not_before(Certificate *self, void *closure)
|
|
{
|
|
PRTime pr_time = 0;
|
|
double d_time;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
pr_time = time_choice_secitem_to_prtime(&self->cert->validity.notBefore);
|
|
LL_L2D(d_time, pr_time);
|
|
|
|
return PyFloat_FromDouble(d_time);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_valid_not_before_str(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return time_choice_secitem_to_pystr(&self->cert->validity.notBefore);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_valid_not_after(Certificate *self, void *closure)
|
|
{
|
|
PRTime pr_time = 0;
|
|
double d_time;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
pr_time = time_choice_secitem_to_prtime(&self->cert->validity.notAfter);
|
|
LL_L2D(d_time, pr_time);
|
|
|
|
return PyFloat_FromDouble(d_time);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_valid_not_after_str(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return time_choice_secitem_to_pystr(&self->cert->validity.notAfter);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_subject(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return DN_new_from_CERTName(&self->cert->subject);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_subject_common_name(Certificate *self, void *closure)
|
|
{
|
|
char *cn;
|
|
PyObject *py_cn = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((cn = CERT_GetCommonName(&self->cert->subject)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
py_cn = PyString_FromString(cn);
|
|
PORT_Free(cn);
|
|
|
|
return py_cn;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_issuer(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return DN_new_from_CERTName(&self->cert->issuer);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_version(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return integer_secitem_to_pylong(&self->cert->version);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_serial_number(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return integer_secitem_to_pylong(&self->cert->serialNumber);
|
|
}
|
|
|
|
// FIXME: should this come from SignedData?
|
|
static PyObject *
|
|
Certificate_get_signature_algorithm(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return AlgorithmID_new_from_SECAlgorithmID(&self->cert->signature);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_signed_data(Certificate *self, void *closure)
|
|
{
|
|
PyObject *py_signed_data = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
return py_signed_data = SignedData_new_from_SECItem(&self->cert->derCert);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_der_data(Certificate *self, void *closure)
|
|
{
|
|
SECItem der;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
der = self->cert->derCert;
|
|
return PyString_FromStringAndSize((char *)der.data, der.len);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_ssl_trust_str(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->cert->trust)
|
|
return cert_trust_flags_str(self->cert->trust->sslFlags, AsEnumDescription);
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_email_trust_str(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->cert->trust)
|
|
return cert_trust_flags_str(self->cert->trust->emailFlags, AsEnumDescription);
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_signing_trust_str(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->cert->trust)
|
|
return cert_trust_flags_str(self->cert->trust->objectSigningFlags, AsEnumDescription);
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_subject_public_key_info(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SubjectPublicKeyInfo_new_from_CERTSubjectPublicKeyInfo(
|
|
&self->cert->subjectPublicKeyInfo);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_extensions(Certificate *self, void *closure)
|
|
{
|
|
CERTCertExtension **extensions = NULL;
|
|
int num_extensions, i;
|
|
PyObject *extensions_tuple;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
/* First count how many extensions the cert has */
|
|
for (extensions = self->cert->extensions, num_extensions = 0;
|
|
extensions && *extensions;
|
|
extensions++, num_extensions++);
|
|
|
|
/* Allocate a tuple */
|
|
if ((extensions_tuple = PyTuple_New(num_extensions)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Copy the extensions into the tuple */
|
|
for (extensions = self->cert->extensions, i = 0; extensions && *extensions; extensions++, i++) {
|
|
CERTCertExtension *extension = *extensions;
|
|
PyObject *py_extension;
|
|
|
|
if ((py_extension = CertificateExtension_new_from_CERTCertExtension(extension)) == NULL) {
|
|
Py_DECREF(extensions_tuple);
|
|
return NULL;
|
|
}
|
|
|
|
PyTuple_SetItem(extensions_tuple, i, py_extension);
|
|
}
|
|
|
|
return extensions_tuple;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_get_cert_type(Certificate *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->cert->nsCertType);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef Certificate_getseters[] = {
|
|
{"valid_not_before", (getter)Certificate_get_valid_not_before, NULL,
|
|
"certificate not valid before this time (floating point value expressed as microseconds since the epoch, midnight January 1st 1970 UTC)", NULL},
|
|
|
|
{"valid_not_before_str", (getter)Certificate_get_valid_not_before_str, NULL,
|
|
"certificate not valid before this time (string value expressed, UTC)", NULL},
|
|
|
|
{"valid_not_after", (getter)Certificate_get_valid_not_after, NULL,
|
|
"certificate not valid after this time (floating point value expressed as microseconds since the epoch, midnight January 1st 1970, UTC)", NULL},
|
|
|
|
{"valid_not_after_str", (getter)Certificate_get_valid_not_after_str, NULL,
|
|
"certificate not valid after this time (string value expressed, UTC)", NULL},
|
|
|
|
{"subject", (getter)Certificate_get_subject, NULL,
|
|
"certificate subject as a `DN` object", NULL},
|
|
|
|
{"subject_common_name", (getter)Certificate_get_subject_common_name, NULL,
|
|
"certificate subject", NULL},
|
|
|
|
{"issuer", (getter)Certificate_get_issuer, NULL,
|
|
"certificate issuer as a `DN` object", NULL},
|
|
|
|
{"version", (getter)Certificate_get_version, NULL,
|
|
"certificate version", NULL},
|
|
|
|
{"serial_number", (getter)Certificate_get_serial_number, NULL,
|
|
"certificate serial number", NULL},
|
|
|
|
{"signature_algorithm", (getter)Certificate_get_signature_algorithm, NULL,
|
|
"certificate signature algorithm", NULL},
|
|
|
|
{"signed_data", (getter)Certificate_get_signed_data, NULL,
|
|
"certificate signature as SignedData object", NULL},
|
|
|
|
{"der_data", (getter)Certificate_get_der_data, NULL,
|
|
"raw certificate DER data as data buffer", NULL},
|
|
|
|
{"ssl_trust_str", (getter)Certificate_get_ssl_trust_str, NULL,
|
|
"certificate SSL trust flags as array of strings, or None if trust is not defined", NULL},
|
|
|
|
{"email_trust_str", (getter)Certificate_get_email_trust_str, NULL,
|
|
"certificate email trust flags as array of strings, or None if trust is not defined", NULL},
|
|
|
|
{"signing_trust_str", (getter)Certificate_get_signing_trust_str, NULL,
|
|
"certificate object signing trust flags as array of strings, or None if trust is not defined", NULL},
|
|
|
|
{"subject_public_key_info", (getter)Certificate_get_subject_public_key_info, NULL,
|
|
"certificate public info as SubjectPublicKeyInfo object", NULL},
|
|
|
|
{"extensions", (getter)Certificate_get_extensions, NULL,
|
|
"certificate extensions as a tuple of CertificateExtension objects", NULL},
|
|
|
|
{"cert_type", (getter)Certificate_get_cert_type, NULL,
|
|
"integer bitmask of NS_CERT_TYPE_* flags, see `nss.cert_type_flags()`", NULL},
|
|
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef Certificate_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(Certificate_find_kea_type_doc,
|
|
"find_kea_type() -> kea_type\n\
|
|
Returns key exchange type of the keys in an SSL server certificate.\n\
|
|
\n\
|
|
May be one of the following:\n\
|
|
- ssl_kea_null\n\
|
|
- ssl_kea_rsa\n\
|
|
- ssl_kea_dh\n\
|
|
- ssl_kea_fortezza (deprecated)\n\
|
|
- ssl_kea_ecdh\n\
|
|
"
|
|
);
|
|
static PyObject *
|
|
Certificate_find_kea_type(Certificate *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(NSS_FindCertKEAType(self->cert));
|
|
}
|
|
|
|
|
|
PyDoc_STRVAR(Certificate_make_ca_nickname_doc,
|
|
"make_ca_nickname() -> string\n\
|
|
Returns a nickname for the certificate guaranteed to be unique\n\
|
|
within the the current NSS database.\n\
|
|
\n\
|
|
The nickname is composed thusly:\n\
|
|
\n\
|
|
A. Establish a name by trying in order:\n\
|
|
\n\
|
|
1. subject's common name (i.e. CN)\n\
|
|
2. subject's organizational unit name (i.e. OU)\n\
|
|
\n\
|
|
B. Establish a realm by trying in order:\n\
|
|
\n\
|
|
1. issuer's organization name (i.e. O)\n\
|
|
2. issuer's distinguished name (i.e. DN)\n\
|
|
3. set to \"Unknown CA\"\n\
|
|
\n\
|
|
C. If name exists the nickname will be \"name - realm\",\n\
|
|
else the nickname will be \"realm\"\n\
|
|
\n\
|
|
D. Then the nickname will be tested for existence in the database.\n\
|
|
If it does not exist it will be returned as the nickname.\n\
|
|
Else a loop is entered where the nickname will have \" #%d\" appended\n\
|
|
to it where %d is an integer beginning at 1. The generated nickname is\n\
|
|
tested for existence in the dabase until a unique name is found.\n\
|
|
\n\
|
|
"
|
|
);
|
|
static PyObject *
|
|
Certificate_make_ca_nickname(Certificate *self, PyObject *args)
|
|
{
|
|
char *nickname = NULL;
|
|
PyObject *py_nickname = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((nickname = CERT_MakeCANickname(self->cert)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
py_nickname = PyString_FromString(nickname);
|
|
PR_smprintf_free(nickname);
|
|
return py_nickname;
|
|
}
|
|
|
|
|
|
PyDoc_STRVAR(Certificate_verify_hostname_doc,
|
|
"verify_hostname(hostname) -> bool\n\
|
|
\n\
|
|
A restricted regular expression syntax is used to test if the common\n\
|
|
name specified in the subject DN of the certificate is a match,\n\
|
|
returning True if so, False otherwise.\n\
|
|
\n\
|
|
The regular expression systax is:\n\
|
|
\\*\n\
|
|
matches anything\n\
|
|
\\?\n\
|
|
matches one character\n\
|
|
\\\\ (backslash)\n\
|
|
escapes a special character\n\
|
|
\\$\n\
|
|
matches the end of the string\n\
|
|
[abc]\n\
|
|
matches one occurrence of a, b, or c. The only character\n\
|
|
that needs to be escaped in this is ], all others are not special.\n\
|
|
[a-z]\n\
|
|
matches any character between a and z\n\
|
|
[^az]\n\
|
|
matches any character except a or z\n\
|
|
\\~\n\
|
|
followed by another shell expression removes any pattern matching\n\
|
|
the shell expression from the match list\n\
|
|
(foo|bar)\n\
|
|
matches either the substring foo or the substring bar.\n\
|
|
These can be shell expressions as well.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_verify_hostname(Certificate *self, PyObject *args)
|
|
{
|
|
char *hostname;
|
|
SECStatus sec_status;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "s:verify_hostname", &hostname))
|
|
return NULL;
|
|
|
|
sec_status = CERT_VerifyCertName(self->cert, hostname);
|
|
|
|
if (sec_status == SECSuccess)
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_has_signer_in_ca_names_doc,
|
|
"has_signer_in_ca_names(ca_names) -> bool\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
ca_names : (SecItem, ...)\n\
|
|
Sequence of CA distinguished names. Each item in the sequence must\n\
|
|
be a SecItem object containing a distinguished name.\n\
|
|
\n\
|
|
Returns True if any of the signers in the certificate chain for a\n\
|
|
specified certificate are in the list of CA names, False\n\
|
|
otherwise.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_has_signer_in_ca_names(Certificate *self, PyObject *args)
|
|
{
|
|
PyObject *py_ca_names = NULL;
|
|
CERTDistNames *ca_names = NULL;
|
|
SECStatus sec_status;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:has_signer_in_ca_names",
|
|
&py_ca_names))
|
|
return NULL;
|
|
|
|
if ((ca_names = cert_distnames_as_CERTDistNames(py_ca_names)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
sec_status = NSS_CmpCertChainWCANames(self->cert, ca_names);
|
|
CERT_FreeDistNames(ca_names);
|
|
|
|
if (sec_status == SECSuccess)
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_check_valid_times_doc,
|
|
"check_valid_times(time=now, allow_override=False) --> validity\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
time : number\n\
|
|
an optional point in time as number of microseconds\n\
|
|
since the NSPR epoch, midnight (00:00:00) 1 January\n\
|
|
1970 UTC, either as an integer or a float. If time \n\
|
|
is not specified the current time is used.\n\
|
|
allow_override : bool\n\
|
|
If True then check to see if the invalidity has\n\
|
|
been overridden by the user, defaults to False.\n\
|
|
\n\
|
|
Checks whether a specified time is within a certificate's validity\n\
|
|
period.\n\
|
|
\n\
|
|
Returns one of:\n\
|
|
\n\
|
|
- secCertTimeValid\n\
|
|
- secCertTimeExpired\n\
|
|
- secCertTimeNotValidYet\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_check_valid_times(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"time", "allow_override", NULL};
|
|
int allow_override = 0;
|
|
PRTime pr_time = 0;
|
|
SECCertTimeValidity validity;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&i:check_valid_times", kwlist,
|
|
PRTimeConvert, &pr_time, &allow_override))
|
|
return NULL;
|
|
|
|
if (!pr_time) {
|
|
pr_time = PR_Now();
|
|
}
|
|
|
|
validity = CERT_CheckCertValidTimes(self->cert, pr_time, allow_override);
|
|
|
|
return PyInt_FromLong(validity);
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_is_ca_cert_doc,
|
|
"is_ca_cert(return_cert_type=False) -> boolean\n\
|
|
is_ca_cert(True) -> boolean, cert_type\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
return_cert_type : boolean\n\
|
|
If True returns both boolean result and certficate\n\
|
|
type bitmask. If False return only boolean result\n\
|
|
\n\
|
|
Returns True if the cert is a CA cert, False otherwise.\n\
|
|
\n\
|
|
The function optionally can return a bitmask of NS_CERT_TYPE_*\n\
|
|
flags if return_cert_type is True. This is the updated cert type\n\
|
|
after applying logic in the context of deciding if the cert is a\n\
|
|
CA cert or not. Hint: the cert_type value can be converted to text\n\
|
|
with `nss.cert_type_flags()`. Hint: the unmodified cert type flags\n\
|
|
can be obtained with the `Certificate.cert_type` property.\n\
|
|
\n\
|
|
");
|
|
static PyObject *
|
|
Certificate_is_ca_cert(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"return_cert_type", NULL};
|
|
int return_cert_type = false;
|
|
PRBool is_ca = PR_FALSE;
|
|
unsigned int cert_type = 0;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:is_ca_cert", kwlist,
|
|
&return_cert_type))
|
|
return NULL;
|
|
|
|
is_ca = CERT_IsCACert(self->cert, return_cert_type ? &cert_type : NULL);
|
|
|
|
|
|
if (return_cert_type) {
|
|
return Py_BuildValue("NI", PyBool_FromLong(is_ca), cert_type);
|
|
} else {
|
|
return PyBool_FromLong(is_ca);
|
|
}
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_verify_now_doc,
|
|
"verify_now(certdb, check_sig, required_usages, [user_data1, ...]) -> valid_usages\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
certdb : CertDB object\n\
|
|
CertDB certificate database object\n\
|
|
check_sig : bool\n\
|
|
True if certificate signatures should be checked\n\
|
|
required_usages : integer\n\
|
|
A bitfield of all cert usages that are required for verification\n\
|
|
to succeed. If zero return all possible valid usages.\n\
|
|
user_dataN : object\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Verify a certificate by checking if it's valid and that we\n\
|
|
trust the issuer.\n\
|
|
\n\
|
|
Possible usage bitfield values are:\n\
|
|
- certificateUsageCheckAllUsages\n\
|
|
- certificateUsageSSLClient\n\
|
|
- certificateUsageSSLServer\n\
|
|
- certificateUsageSSLServerWithStepUp\n\
|
|
- certificateUsageSSLCA\n\
|
|
- certificateUsageEmailSigner\n\
|
|
- certificateUsageEmailRecipient\n\
|
|
- certificateUsageObjectSigner\n\
|
|
- certificateUsageUserCertImport\n\
|
|
- certificateUsageVerifyCA\n\
|
|
- certificateUsageProtectedObjectSigner\n\
|
|
- certificateUsageStatusResponder\n\
|
|
- certificateUsageAnyCA\n\
|
|
\n\
|
|
Returns valid_usages, a bitfield of certificate usages. If\n\
|
|
required_usages is non-zero, the returned bitmap is only for those\n\
|
|
required usages, otherwise it is for all possible usages.\n\
|
|
\n\
|
|
Hint: You can obtain a printable representation of the usage flags\n\
|
|
via `cert_usage_flags`.\n\
|
|
\n\
|
|
Note: See the `Certificate.verify` documentation for details on how\n\
|
|
the Certificate verification functions handle errors.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_verify_now(Certificate *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 3;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
CertDB *py_certdb = NULL;
|
|
PyObject *py_check_sig = NULL;
|
|
PRBool check_sig = 0;
|
|
long required_usages = 0;
|
|
SECCertificateUsage returned_usages = 0;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "O!O!l:verify_now",
|
|
&CertDBType, &py_certdb,
|
|
&PyBool_Type, &py_check_sig,
|
|
&required_usages)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
check_sig = PyBoolAsPRBool(py_check_sig);
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (CERT_VerifyCertificateNow(py_certdb->handle, self->cert, check_sig,
|
|
required_usages, pin_args, &returned_usages) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_cert_verify_error(returned_usages, NULL, NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
Py_DECREF(pin_args);
|
|
|
|
return PyInt_FromLong(returned_usages);
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_verify_doc,
|
|
"verify(certdb, check_sig, required_usages, time, [user_data1, ...]) -> valid_usages\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
certdb : CertDB object\n\
|
|
CertDB certificate database object\n\
|
|
check_sig : bool\n\
|
|
True if certificate signatures should be checked\n\
|
|
required_usages : integer\n\
|
|
A bitfield of all cert usages that are required for verification\n\
|
|
to succeed. If zero return all possible valid usages.\n\
|
|
time : number\n\
|
|
an optional point in time as number of microseconds\n\
|
|
since the NSPR epoch, midnight (00:00:00) 1 January\n\
|
|
1970 UTC, either as an integer or a float. If time \n\
|
|
is not specified the current time is used.\n\
|
|
user_dataN : object\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Verify a certificate by checking if it's valid and that we\n\
|
|
trust the issuer.\n\
|
|
\n\
|
|
Possible usage bitfield values are:\n\
|
|
- certificateUsageCheckAllUsages\n\
|
|
- certificateUsageSSLClient\n\
|
|
- certificateUsageSSLServer\n\
|
|
- certificateUsageSSLServerWithStepUp\n\
|
|
- certificateUsageSSLCA\n\
|
|
- certificateUsageEmailSigner\n\
|
|
- certificateUsageEmailRecipient\n\
|
|
- certificateUsageObjectSigner\n\
|
|
- certificateUsageUserCertImport\n\
|
|
- certificateUsageVerifyCA\n\
|
|
- certificateUsageProtectedObjectSigner\n\
|
|
- certificateUsageStatusResponder\n\
|
|
- certificateUsageAnyCA\n\
|
|
\n\
|
|
Returns valid_usages, a bitfield of certificate usages.\n\
|
|
\n\
|
|
If required_usages is non-zero, the returned bitmap is only for those\n\
|
|
required usages, otherwise it is for all possible usages.\n\
|
|
\n\
|
|
Hint: You can obtain a printable representation of the usage flags\n\
|
|
via `cert_usage_flags`.\n\
|
|
\n\
|
|
Note: Anytime a NSPR or NSS function returns an error in python-nss it\n\
|
|
raises a NSPRError exception. When an exception is raised the normal\n\
|
|
return values are discarded because the flow of control continues at\n\
|
|
the first except block prepared to catch the exception. Normally this\n\
|
|
is what is desired because the return values would be invalid due to\n\
|
|
the error. However the certificate verification functions are an\n\
|
|
exception (no pun intended). An error might be returned indicating the\n\
|
|
cert failed verification but you may still need access to the returned\n\
|
|
usage bitmask and the log (if using the log variant). To handle this a\n\
|
|
special error exception `CertVerifyError` (derived from `NSPRError`)\n\
|
|
is defined which in addition to the normal NSPRError fields will also\n\
|
|
contain the returned usages and optionally the CertVerifyLog\n\
|
|
object. If no exception is raised these are returned as normal return\n\
|
|
values.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_verify(Certificate *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 4;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
CertDB *py_certdb = NULL;
|
|
PyObject *py_check_sig = NULL;
|
|
PRBool check_sig = 0;
|
|
PRTime pr_time = 0;
|
|
long required_usages = 0;
|
|
SECCertificateUsage returned_usages = 0;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "O!O!lO&:verify",
|
|
&CertDBType, &py_certdb,
|
|
&PyBool_Type, &py_check_sig,
|
|
&required_usages,
|
|
PRTimeConvert, &pr_time)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
check_sig = PyBoolAsPRBool(py_check_sig);
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (CERT_VerifyCertificate(py_certdb->handle, self->cert, check_sig,
|
|
required_usages, pr_time, pin_args,
|
|
NULL, &returned_usages) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_cert_verify_error(returned_usages, NULL, NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
Py_DECREF(pin_args);
|
|
|
|
return PyInt_FromLong(returned_usages);
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_verify_with_log_doc,
|
|
"verify_with_log(certdb, check_sig, required_usages, time, [user_data1, ...]) -> valid_usages, log\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
certdb : CertDB object\n\
|
|
CertDB certificate database object\n\
|
|
check_sig : bool\n\
|
|
True if certificate signatures should be checked\n\
|
|
required_usages : integer\n\
|
|
A bitfield of all cert usages that are required for verification\n\
|
|
to succeed. If zero return all possible valid usages.\n\
|
|
time : number\n\
|
|
an optional point in time as number of microseconds\n\
|
|
since the NSPR epoch, midnight (00:00:00) 1 January\n\
|
|
1970 UTC, either as an integer or a float. If time \n\
|
|
is not specified the current time is used.\n\
|
|
user_dataN : object\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Verify a certificate by checking if it's valid and that we\n\
|
|
trust the issuer.\n\
|
|
\n\
|
|
Possible usage bitfield values are:\n\
|
|
- certificateUsageCheckAllUsages\n\
|
|
- certificateUsageSSLClient\n\
|
|
- certificateUsageSSLServer\n\
|
|
- certificateUsageSSLServerWithStepUp\n\
|
|
- certificateUsageSSLCA\n\
|
|
- certificateUsageEmailSigner\n\
|
|
- certificateUsageEmailRecipient\n\
|
|
- certificateUsageObjectSigner\n\
|
|
- certificateUsageUserCertImport\n\
|
|
- certificateUsageVerifyCA\n\
|
|
- certificateUsageProtectedObjectSigner\n\
|
|
- certificateUsageStatusResponder\n\
|
|
- certificateUsageAnyCA\n\
|
|
\n\
|
|
Returns valid_usages, a bitfield of certificate usages and a `nss.CertVerifyLog`\n\
|
|
object with diagnostic information detailing the reasons for a validation failure.\n\
|
|
\n\
|
|
If required_usages is non-zero, the returned bitmap is only for those\n\
|
|
required usages, otherwise it is for all possible usages.\n\
|
|
\n\
|
|
Hint: You can obtain a printable representation of the usage flags\n\
|
|
via `cert_usage_flags`.\n\
|
|
\n\
|
|
Note: See the `Certificate.verify` documentation for details on how\n\
|
|
the Certificate verification functions handle errors.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_verify_with_log(Certificate *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 4;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
CertDB *py_certdb = NULL;
|
|
PyObject *py_check_sig = NULL;
|
|
PRBool check_sig = 0;
|
|
PRTime pr_time = 0;
|
|
CertVerifyLog *py_log = NULL;
|
|
long required_usages = 0;
|
|
SECCertificateUsage returned_usages = 0;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "O!O!lO&:verify_with_log",
|
|
&CertDBType, &py_certdb,
|
|
&PyBool_Type, &py_check_sig,
|
|
&required_usages,
|
|
PRTimeConvert, &pr_time)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
check_sig = PyBoolAsPRBool(py_check_sig);
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
if ((py_log = (CertVerifyLog *)CertVerifyLog_new(&CertVerifyLogType, NULL, NULL)) == NULL) {
|
|
Py_DECREF(pin_args);
|
|
return NULL;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (CERT_VerifyCertificate(py_certdb->handle, self->cert, check_sig,
|
|
required_usages, pr_time, pin_args,
|
|
&py_log->log, &returned_usages) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_cert_verify_error(returned_usages, (PyObject *)py_log, NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
Py_DECREF(pin_args);
|
|
|
|
return Py_BuildValue("KN", returned_usages, py_log);
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_get_extension_doc,
|
|
"get_extension(oid) -> `CertificateExtension`\n\
|
|
\n\
|
|
Given an oid identifying the extension try to locate it in the\n\
|
|
certificate and return it as generic `CertificateExtension` object. If\n\
|
|
the extension is not present raise a KeyError.\n\
|
|
\n\
|
|
The generic `CertificateExtension` object is not terribly useful on\n\
|
|
it's own, howerver it's value property can be used to intialize\n\
|
|
instances of a class representing the extension. Or it may be passed\n\
|
|
to functions that convert the value into some other usable format.\n\
|
|
Although one might believe this function should do these conversions\n\
|
|
for you automatically there are too many possible variations. Plus one\n\
|
|
might simple be interested to know if an extension is present or\n\
|
|
not. So why perform conversion work that might not be needed or might\n\
|
|
not be in the format needed? Therefore this function is just one\n\
|
|
simple element in a larger toolbox. Below are some suggestions on how\n\
|
|
to convert the generic `CertificateExtension` object (this list may\n\
|
|
not be complete).\n\
|
|
\n\
|
|
SEC_OID_PKCS12_KEY_USAGE\n\
|
|
`x509_key_usage()`\n\
|
|
SEC_OID_X509_SUBJECT_KEY_ID\n\
|
|
`SecItem.der_to_hex()`\n\
|
|
SEC_OID_X509_CRL_DIST_POINTS\n\
|
|
`CRLDistributionPts()`\n\
|
|
case SEC_OID_X509_AUTH_KEY_ID\n\
|
|
`AuthKeyID()`\n\
|
|
SEC_OID_X509_EXT_KEY_USAGE\n\
|
|
`x509_ext_key_usage()`\n\
|
|
SEC_OID_X509_BASIC_CONSTRAINTS\n\
|
|
`BasicConstraints()`\n\
|
|
SEC_OID_X509_SUBJECT_ALT_NAME\n\
|
|
`x509_alt_name()`\n\
|
|
SEC_OID_X509_ISSUER_ALT_NAME\n\
|
|
`x509_alt_name()`\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
oid : may be one of integer, string, SecItem\n\
|
|
The OID of the certification extension to retreive\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* integer: A SEC OID enumeration constant (i.e. SEC_OID\\_*)\n\
|
|
for example SEC_OID_X509_BASIC_CONSTRAINTS.\n\
|
|
* string: A string either the OID name, with or without the SEC_OID\\_\n\
|
|
prefix (e.g. \"SEC_OID_X509_BASIC_CONSTRAINTS\" or \"X509_BASIC_CONSTRAINTS\")\n\
|
|
or as the dotted decimal representation, for example\n\
|
|
'OID.2 5 29 19'. Case is not significant for either form.\n\
|
|
* SecItem: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
\n\
|
|
:returns:\n\
|
|
generic `CertificateExtension` object\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_get_extension(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"oid", NULL};
|
|
PyObject *py_oid;
|
|
SECOidTag oid_tag = SEC_OID_UNKNOWN;
|
|
SECOidTag cur_oid_tag = SEC_OID_UNKNOWN;
|
|
CERTCertExtension **extensions = NULL;
|
|
CERTCertExtension *cur_extension = NULL, *extension = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:get_extension", kwlist,
|
|
&py_oid))
|
|
return NULL;
|
|
|
|
if ((oid_tag = get_oid_tag_from_object(py_oid)) == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
extension = NULL;
|
|
for (extensions = self->cert->extensions; extensions && *extensions; extensions++) {
|
|
cur_extension = *extensions;
|
|
|
|
cur_oid_tag = SECOID_FindOIDTag(&cur_extension->id);
|
|
|
|
if (cur_oid_tag == SEC_OID_UNKNOWN) {
|
|
continue;
|
|
}
|
|
|
|
if (oid_tag == cur_oid_tag) {
|
|
extension = cur_extension;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (extension == NULL) {
|
|
PyObject *py_oid_name = NULL;
|
|
|
|
if ((py_oid_name = oid_tag_name_from_tag(oid_tag)) == NULL) {
|
|
py_oid_name = PyObject_Str(py_oid);
|
|
}
|
|
PyErr_Format(PyExc_KeyError, "no extension with OID %s found",
|
|
PyString_AsString(py_oid_name));
|
|
Py_DECREF(py_oid_name);
|
|
return NULL;
|
|
}
|
|
|
|
return CertificateExtension_new_from_CERTCertExtension(extension);
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_get_cert_chain_doc,
|
|
"get_cert_chain(time=now, usages=certUsageAnyCA) -> (`Certificate`, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
time : number\n\
|
|
an optional point in time as number of microseconds\n\
|
|
since the NSPR epoch, midnight (00:00:00) 1 January\n\
|
|
1970 UTC, either as an integer or a float. If time \n\
|
|
is not specified the current time is used.\n\
|
|
usages : integer\n\
|
|
a certUsage* enumerated constant\n\
|
|
\n\
|
|
Returns a tuple of `Certificate` objects.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
Certificate_get_cert_chain(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"time", "usages", NULL};
|
|
PRTime pr_time = 0;
|
|
int usages = certUsageAnyCA;
|
|
CERTCertList *cert_list = NULL;
|
|
PyObject *tuple = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&i:get_cert_chain", kwlist,
|
|
PRTimeConvert, &pr_time, &usages))
|
|
return NULL;
|
|
|
|
if ((cert_list = CERT_GetCertChainFromCert(self->cert, pr_time, usages)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
tuple = CERTCertList_to_tuple(cert_list);
|
|
CERT_DestroyCertList(cert_list);
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_summary_format_lines(Certificate *self, int level, PyObject *lines)
|
|
{
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
PyObject *obj2 = NULL;
|
|
|
|
if ((obj = Certificate_get_subject(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Subject"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = Certificate_get_issuer(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Issuer"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj1 = Certificate_get_valid_not_before_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj2 = Certificate_get_valid_not_after_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj = obj_sprintf("[%s] - [%s]", obj1, obj2)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(obj1);
|
|
Py_CLEAR(obj2);
|
|
FMT_OBJ_AND_APPEND(lines, _("Validity"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(obj2);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_format_lines(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
Py_ssize_t len, i;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
PyObject *obj2 = NULL;
|
|
PyObject *obj3 = NULL;
|
|
PyObject *obj_line_fmt_tuples = NULL;
|
|
PyObject *obj_lines = NULL;
|
|
PyObject *ssl_trust_lines = NULL, *email_trust_lines = NULL, *signing_trust_lines = NULL;
|
|
PyObject *tmp_args = NULL;
|
|
PyObject *extensions = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Data"), level, fail);
|
|
|
|
if ((obj = Certificate_get_version(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj1 = PyInt_FromLong(1)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj2 = PyNumber_Add(obj, obj1)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj3 = obj_sprintf("%d (%#x)", obj2, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Version"), obj3, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
Py_CLEAR(obj1);
|
|
Py_CLEAR(obj2);
|
|
Py_CLEAR(obj3);
|
|
|
|
if ((obj = Certificate_get_serial_number(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj1 = obj_sprintf("%d (%#x)", obj, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Serial Number"), obj1, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
Py_CLEAR(obj1);
|
|
|
|
if ((obj = Certificate_get_signature_algorithm(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_LABEL_AND_APPEND(lines, _("Signature Algorithm"), level+2, fail);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+3, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = Certificate_get_issuer(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Issuer"), obj, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Validity"), level+2, fail);
|
|
|
|
if ((obj = Certificate_get_valid_not_before_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Not Before"), obj, level+3, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = Certificate_get_valid_not_after_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Not After"), obj, level+3, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = Certificate_get_subject(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Subject"), obj, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Subject Public Key Info"), level+2, fail);
|
|
|
|
if ((obj = Certificate_get_subject_public_key_info(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+3, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((extensions = Certificate_get_extensions(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
len = PyTuple_Size(extensions);
|
|
if ((obj = PyString_FromFormat("Signed Extensions: (%d)", len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
obj = PyTuple_GetItem(extensions, i);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+2, fail);
|
|
FMT_LABEL_AND_APPEND(lines, NULL, 0, fail);
|
|
}
|
|
Py_CLEAR(extensions);
|
|
|
|
if ((ssl_trust_lines = Certificate_get_ssl_trust_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((email_trust_lines = Certificate_get_email_trust_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((signing_trust_lines = Certificate_get_signing_trust_str(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((ssl_trust_lines != Py_None) || (email_trust_lines != Py_None) || (signing_trust_lines != Py_None)) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Certificate Trust Flags"), level+2, fail);
|
|
|
|
if (PyList_Check(ssl_trust_lines)) {
|
|
FMT_LABEL_AND_APPEND(lines, _("SSL Flags"), level+3, fail);
|
|
APPEND_LINES_AND_CLEAR(lines, ssl_trust_lines, level+4, fail);
|
|
}
|
|
|
|
if (PyList_Check(email_trust_lines)) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Email Flags"), level+3, fail);
|
|
APPEND_LINES_AND_CLEAR(lines, email_trust_lines, level+4, fail);
|
|
}
|
|
|
|
if (PyList_Check(signing_trust_lines)) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Object Signing Flags"), level+3, fail);
|
|
APPEND_LINES_AND_CLEAR(lines, signing_trust_lines, level+4, fail);
|
|
}
|
|
|
|
}
|
|
Py_CLEAR(ssl_trust_lines);
|
|
Py_CLEAR(email_trust_lines);
|
|
Py_CLEAR(signing_trust_lines);
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Signature"), level+1, fail);
|
|
|
|
if ((obj = Certificate_get_signed_data(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(obj2);
|
|
Py_XDECREF(obj3);
|
|
Py_XDECREF(lines);
|
|
Py_XDECREF(obj_line_fmt_tuples);
|
|
Py_XDECREF(obj_lines);
|
|
Py_XDECREF(tmp_args);
|
|
Py_XDECREF(ssl_trust_lines);
|
|
Py_XDECREF(email_trust_lines);
|
|
Py_XDECREF(signing_trust_lines);
|
|
Py_XDECREF(extensions);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_format(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)Certificate_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_str(Certificate *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
py_formatted_result = Certificate_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef Certificate_methods[] = {
|
|
{"find_kea_type", (PyCFunction)Certificate_find_kea_type, METH_NOARGS, Certificate_find_kea_type_doc},
|
|
{"make_ca_nickname", (PyCFunction)Certificate_make_ca_nickname, METH_NOARGS, Certificate_make_ca_nickname_doc},
|
|
{"has_signer_in_ca_names", (PyCFunction)Certificate_has_signer_in_ca_names, METH_VARARGS, Certificate_has_signer_in_ca_names_doc},
|
|
{"verify_hostname", (PyCFunction)Certificate_verify_hostname, METH_VARARGS, Certificate_verify_hostname_doc},
|
|
{"check_valid_times", (PyCFunction)Certificate_check_valid_times, METH_VARARGS|METH_KEYWORDS, Certificate_check_valid_times_doc},
|
|
{"is_ca_cert", (PyCFunction)Certificate_is_ca_cert, METH_VARARGS|METH_KEYWORDS, Certificate_is_ca_cert_doc},
|
|
{"verify_now", (PyCFunction)Certificate_verify_now, METH_VARARGS, Certificate_verify_now_doc},
|
|
{"verify", (PyCFunction)Certificate_verify, METH_VARARGS, Certificate_verify_doc},
|
|
{"verify_with_log", (PyCFunction)Certificate_verify_with_log, METH_VARARGS, Certificate_verify_with_log_doc},
|
|
{"get_cert_chain", (PyCFunction)Certificate_get_cert_chain, METH_VARARGS|METH_KEYWORDS, Certificate_get_cert_chain_doc},
|
|
{"get_extension", (PyCFunction)Certificate_get_extension, METH_VARARGS|METH_KEYWORDS, Certificate_get_extension_doc},
|
|
{"format_lines", (PyCFunction)Certificate_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)Certificate_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
Certificate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
Certificate *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (Certificate *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
self->cert = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
Certificate_dealloc(Certificate* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->cert) {
|
|
CERT_DestroyCertificate(self->cert);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(Certificate_doc,
|
|
"Certificate(data=None, der_is_signed=True)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : SecItem or str or any buffer compatible object\n\
|
|
Data to initialize the certificate from, must be in DER format\n\
|
|
der_is_signed : bool\n\
|
|
True if certficate DER data is wrapped by signed DER data.\n\
|
|
If False then DER data is certifcate only.\n\
|
|
\n\
|
|
An object representing a Certificate");
|
|
|
|
static int
|
|
Certificate_init(Certificate *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"data", "der_is_signed", NULL};
|
|
PyObject *py_data = NULL;
|
|
int der_is_signed = 1;
|
|
SECItem tmp_item;
|
|
SECItem *der_item = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:Certificate", kwlist,
|
|
&py_data, &der_is_signed))
|
|
return -1;
|
|
|
|
SECITEM_PARAM(py_data, der_item, tmp_item, false, "data");
|
|
|
|
if (py_data) {
|
|
if (der_is_signed) {
|
|
return Certificate_init_from_signed_der_secitem(self, der_item);
|
|
} else {
|
|
return Certificate_init_from_unsigned_der_secitem(self, der_item);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
Certificate_repr(Certificate *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p Certificate %p>",
|
|
Py_TYPE(self)->tp_name, self, self->cert);
|
|
}
|
|
|
|
static PyTypeObject CertificateType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.Certificate", /* tp_name */
|
|
sizeof(Certificate), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)Certificate_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)Certificate_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)Certificate_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
Certificate_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
Certificate_methods, /* tp_methods */
|
|
Certificate_members, /* tp_members */
|
|
Certificate_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)Certificate_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
Certificate_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
Certificate_new_from_CERTCertificate(CERTCertificate *cert)
|
|
{
|
|
Certificate *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (Certificate *) CertificateType.tp_new(&CertificateType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->cert = CERT_DupCertificate(cert)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
static int
|
|
Certificate_init_from_signed_der_secitem(Certificate *self, SECItem *der)
|
|
{
|
|
CERTCertificate *cert = NULL;
|
|
|
|
if ((cert = CERT_DecodeDERCertificate(der, PR_TRUE, NULL)) == NULL) {
|
|
set_nspr_error("bad signed certificate DER data");
|
|
return -1;
|
|
}
|
|
|
|
self->cert = cert;
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
Certificate_new_from_signed_der_secitem(SECItem *der)
|
|
{
|
|
Certificate *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (Certificate *) CertificateType.tp_new(&CertificateType, NULL, NULL)) == NULL) {
|
|
TraceObjNewLeave(self);
|
|
return NULL;
|
|
}
|
|
|
|
if (Certificate_init_from_signed_der_secitem(self, der) != 0) {
|
|
Py_CLEAR(self);
|
|
TraceObjNewLeave(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
static int
|
|
Certificate_init_from_unsigned_der_secitem(Certificate *self, SECItem *der)
|
|
{
|
|
CERTCertificate *cert = NULL;
|
|
PRArenaPool *arena = NULL;
|
|
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
|
|
if ((cert = PORT_ArenaZNew(arena, CERTCertificate)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return -1;
|
|
}
|
|
cert->arena = arena;
|
|
|
|
if (SEC_ASN1DecodeItem(arena, cert, SEC_ASN1_GET(CERT_CertificateTemplate), der) != SECSuccess) {
|
|
set_nspr_error("bad unsigned certificate DER data");
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return -1;
|
|
}
|
|
|
|
self->cert = cert;
|
|
return 0;
|
|
}
|
|
|
|
#if 0 /* currently unused */
|
|
static PyObject *
|
|
Certificate_new_from_unsigned_der_secitem(SECItem *der)
|
|
{
|
|
Certificate *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (Certificate *) CertificateType.tp_new(&CertificateType, NULL, NULL)) == NULL) {
|
|
TraceObjNewLeave(self);
|
|
return NULL;
|
|
}
|
|
|
|
if (Certificate_init_from_unsigned_der_secitem(self, der) != 0) {
|
|
Py_CLEAR(self);
|
|
TraceObjNewLeave(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
#endif
|
|
|
|
/* ========================================================================== */
|
|
/* ============================= PrivateKey Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef PrivateKey_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PrivateKey_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
|
|
static PyMethodDef PrivateKey_methods[] = {
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
PrivateKey_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
PrivateKey *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (PrivateKey *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
self->private_key = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
PrivateKey_dealloc(PrivateKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->private_key)
|
|
SECKEY_DestroyPrivateKey(self->private_key);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PrivateKey_doc,
|
|
"An object representing a Private Key");
|
|
|
|
static int
|
|
PrivateKey_init(PrivateKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject PrivateKeyType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PrivateKey", /* tp_name */
|
|
sizeof(PrivateKey), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PrivateKey_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
PrivateKey_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PrivateKey_methods, /* tp_methods */
|
|
PrivateKey_members, /* tp_members */
|
|
PrivateKey_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PrivateKey_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PrivateKey_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
PrivateKey_new_from_SECKEYPrivateKey(SECKEYPrivateKey *private_key)
|
|
{
|
|
PrivateKey *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
if ((self = (PrivateKey *) PrivateKeyType.tp_new(&PrivateKeyType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->private_key = private_key;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
|
|
/* ========================================================================== */
|
|
/* ============================== SignedCRL Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef SignedCRL_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef SignedCRL_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(SignedCRL_delete_permanently_doc,
|
|
"delete_permanently()\n\
|
|
\n\
|
|
Permanently remove the CRL from the database.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
SignedCRL_delete_permanently(SignedCRL *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (SEC_DeletePermCRL(self->signed_crl) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyMethodDef SignedCRL_methods[] = {
|
|
{"delete_permanently", (PyCFunction)SignedCRL_delete_permanently, METH_NOARGS, SignedCRL_delete_permanently_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
SignedCRL_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
SignedCRL *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (SignedCRL *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
self->signed_crl = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
SignedCRL_dealloc(SignedCRL* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->signed_crl)
|
|
SEC_DestroyCrl(self->signed_crl);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(SignedCRL_doc,
|
|
"An object representing a signed certificate revocation list");
|
|
|
|
static int
|
|
SignedCRL_init(SignedCRL *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject SignedCRLType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.SignedCRL", /* tp_name */
|
|
sizeof(SignedCRL), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)SignedCRL_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
SignedCRL_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
SignedCRL_methods, /* tp_methods */
|
|
SignedCRL_members, /* tp_members */
|
|
SignedCRL_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)SignedCRL_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
SignedCRL_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
SignedCRL_new_from_CERTSignedCRL(CERTSignedCrl *signed_crl)
|
|
{
|
|
SignedCRL *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
if ((self = (SignedCRL *) SignedCRLType.tp_new(&SignedCRLType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->signed_crl = signed_crl;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =============================== AVA Class ================================ */
|
|
/* ========================================================================== */
|
|
|
|
/*
|
|
* Note: CERT_CopyAVA, CERT_GetAVATag, CERT_CompareAVA, CERT_CreateAVA,
|
|
* and CERT_DecodeAVAValue are defined in cert.h
|
|
*
|
|
* But only CERT_GetAVATag, CERT_CreateAVA, CERT_DecodeAVAValue are exported
|
|
* by nss.def
|
|
*
|
|
* That means CERT_CopyAVA and CERT_CompareAVA are defined as public but aren't.
|
|
*/
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
AVA_get_oid(AVA *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SecItem_new_from_SECItem(&self->ava->type, SECITEM_oid);
|
|
}
|
|
|
|
static PyObject *
|
|
AVA_get_oid_tag(AVA *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(CERT_GetAVATag(self->ava));
|
|
}
|
|
|
|
static PyObject *
|
|
AVA_get_value(AVA *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SecItem_new_from_SECItem(&self->ava->value, SECITEM_utf8_string);
|
|
}
|
|
|
|
static PyObject *
|
|
AVA_get_value_str(AVA *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return AVA_repr(self);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef AVA_getseters[] = {
|
|
{"oid", (getter)AVA_get_oid, (setter)NULL,
|
|
"The OID (e.g. type) of the AVA as a SecItem", NULL},
|
|
{"oid_tag", (getter)AVA_get_oid_tag, (setter)NULL,
|
|
"The OID tag enumerated constant (i.e. SEC_OID_AVA_*) of the AVA's type", NULL},
|
|
{"value", (getter)AVA_get_value, (setter)NULL,
|
|
"The value of the AVA as a SecItem", NULL},
|
|
{"value_str", (getter)AVA_get_value_str, (setter)NULL,
|
|
"The value of the AVA as a UTF-8 encoded string", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef AVA_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
|
|
/*
|
|
* Compares two CERTAVA's, returns -1 if a < b, 0 if a == b, 1 if a > b
|
|
* If error, returns -2
|
|
*/
|
|
static int
|
|
CERTAVA_compare(CERTAVA *a, CERTAVA *b)
|
|
{
|
|
SECComparison sec_cmp_result;
|
|
int int_cmp_result;
|
|
PyObject *a_val_str, *b_val_str;
|
|
|
|
if (a == NULL && b == NULL) return 0;
|
|
if (a == NULL && b != NULL) return -1;
|
|
if (a != NULL && b == NULL) return 1;
|
|
|
|
if ((sec_cmp_result = SECITEM_CompareItem(&a->type, &b->type)) != SECEqual) {
|
|
#if 0 /* FIXME when https://bugzilla.redhat.com/show_bug.cgi?id=804802 is fixed */
|
|
return sec_cmp_result == SECLessThan ? -1 : 1;
|
|
#else
|
|
return sec_cmp_result < 0 ? SECLessThan : SECGreaterThan;
|
|
#endif
|
|
}
|
|
|
|
/* Attribute types matched, are values equal? */
|
|
if ((sec_cmp_result = SECITEM_CompareItem(&a->value,
|
|
&b->value)) == SECEqual) {
|
|
return 0;
|
|
}
|
|
|
|
/* No values not equal, compare as case insenstive strings */
|
|
a_val_str = CERTAVA_value_to_pystr(a);
|
|
b_val_str = CERTAVA_value_to_pystr(b);
|
|
if (a_val_str == NULL || b_val_str == NULL) {
|
|
Py_XDECREF(a_val_str);
|
|
Py_XDECREF(b_val_str);
|
|
PyErr_SetString(PyExc_ValueError, "Failed to convert AVA value to string");
|
|
return -2;
|
|
}
|
|
|
|
int_cmp_result = strcasecmp(PyString_AS_STRING(a_val_str),
|
|
PyString_AS_STRING(b_val_str));
|
|
Py_DECREF(a_val_str);
|
|
Py_DECREF(b_val_str);
|
|
return (int_cmp_result == 0) ? 0 : ((int_cmp_result < 0) ? -1 : 1);
|
|
}
|
|
|
|
static int
|
|
AVA_compare(AVA *self, AVA *other)
|
|
{
|
|
int cmp_result;
|
|
|
|
if (!PyAVA_Check(other)) {
|
|
PyErr_SetString(PyExc_TypeError, "Bad type, must be AVA");
|
|
return -1;
|
|
}
|
|
|
|
cmp_result = CERTAVA_compare(self->ava, other->ava);
|
|
if (cmp_result == -2) {
|
|
return -1;
|
|
}
|
|
return cmp_result;
|
|
}
|
|
|
|
static PyMethodDef AVA_methods[] = {
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
AVA_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
AVA *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (AVA *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->ava = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
AVA_dealloc(AVA* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(AVA_doc,
|
|
"An object representing an AVA (attribute value assertion).\n\
|
|
\n\
|
|
AVA(type, value)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
type : may be one of integer, string, SecItem\n\
|
|
What kind of attribute is being created. May be\n\
|
|
one of:\n\
|
|
\n\
|
|
* integer: A SEC OID enumeration constant (i.e. SEC_OID_*)\n\
|
|
for example SEC_OID_AVA_COMMON_NAME.\n\
|
|
* string: A string either as the ava name, for example 'cn'\n\
|
|
or as the dotted decimal representation, for example\n\
|
|
'OID.2.5.4.3'. Case is not significant for either form.\n\
|
|
* SecItem: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
value : string\n\
|
|
The value of the AVA, must be a string.\n\
|
|
\n\
|
|
RDN's (Relative Distinguished Name) are composed from AVA's.\n\
|
|
An `RDN` is a sequence of AVA's.\n\
|
|
\n\
|
|
An example of an AVA is \"CN=www.redhat.com\" where CN is the X500\n\
|
|
directory abbrevation for \"Common Name\".\n\
|
|
\n\
|
|
An AVA is composed of two items:\n\
|
|
\n\
|
|
type\n\
|
|
Specifies the attribute (e.g. CN). AVA types are specified by\n\
|
|
predefined OID's (Object Identifiers). For example the OID of CN\n\
|
|
is 2.5.4.3 ({joint-iso-itu-t(2) ds(5) attributeType(4) commonName(3)})\n\
|
|
OID's in NSS are encapsulated in a SecItem as a DER encoded OID.\n\
|
|
Because DER encoded OID's are less than ideal mechanisms by which\n\
|
|
to specify an item NSS has mapped each OID to a integral enumerated\n\
|
|
constant called an OID tag (i.e. SEC_OID_*). Many of the NSS API's\n\
|
|
will accept an OID tag number instead of DER encoded OID in a SecItem.\n\
|
|
One can easily convert between DER encoded OID's, tags, and their\n\
|
|
string representation in dotted-decimal format. The enumerated OID\n\
|
|
constants are the most efficient in most cases.\n\
|
|
value\n\
|
|
The value of the attribute (e.g. 'www.redhat.com').\n\
|
|
\n\
|
|
Examples::\n\
|
|
\n\
|
|
The AVA cn=www.redhat.com can be created in any of the follow ways:\n\
|
|
\n\
|
|
ava = nss.AVA('cn', 'www.redhat.com')\n\
|
|
ava = nss.AVA(nss.SEC_OID_AVA_COMMON_NAME, 'www.redhat.com')\n\
|
|
ava = nss.AVA('2.5.4.3', 'www.redhat.com')\n\
|
|
ava = nss.AVA('OID.2.5.4.3', 'www.redhat.com')\n\
|
|
");
|
|
|
|
static int
|
|
AVA_init(AVA *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"type", "value", NULL};
|
|
PyObject *py_type = NULL;
|
|
PyObject *py_value = NULL;
|
|
PyObject *py_value_utf8 = NULL;
|
|
int oid_tag = SEC_OID_UNKNOWN;
|
|
int value_type;
|
|
char *value_string;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:AVA", kwlist,
|
|
&py_type, &py_value))
|
|
return -1;
|
|
|
|
if ((oid_tag = get_oid_tag_from_object(py_type)) == -1) {
|
|
return -1;
|
|
}
|
|
|
|
if (oid_tag == SEC_OID_UNKNOWN) {
|
|
PyObject *type_str = PyObject_Str(py_type);
|
|
PyErr_Format(PyExc_ValueError, "unable to convert \"%s\" to known OID",
|
|
PyString_AsString(type_str));
|
|
Py_DECREF(type_str);
|
|
return -1;
|
|
}
|
|
|
|
if (PyString_Check(py_value) || PyUnicode_Check(py_value)) {
|
|
if (PyString_Check(py_value)) {
|
|
py_value_utf8 = py_value;
|
|
Py_INCREF(py_value_utf8);
|
|
} else {
|
|
py_value_utf8 = PyUnicode_AsUTF8String(py_value);
|
|
}
|
|
|
|
if ((value_string = PyString_AsString(py_value_utf8)) == NULL) {
|
|
Py_DECREF(py_value_utf8);
|
|
return -1;
|
|
}
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError, "AVA value must be a string, not %.200s",
|
|
Py_TYPE(py_type)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
value_type = ava_oid_tag_to_value_type(oid_tag);
|
|
if ((self->ava = CERT_CreateAVA(self->arena, oid_tag, value_type, value_string)) == NULL) {
|
|
set_nspr_error("could not create AVA, oid tag = %d, value = \"%s\"",
|
|
oid_tag, value_string);
|
|
Py_XDECREF(py_value_utf8);
|
|
return -1;
|
|
}
|
|
|
|
Py_XDECREF(py_value_utf8);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
AVA_repr(AVA *self)
|
|
{
|
|
PyObject *py_value_str;
|
|
|
|
if ((py_value_str = CERTAVA_value_to_pystr(self->ava)) == NULL) {
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
return py_value_str;
|
|
}
|
|
|
|
static PyTypeObject AVAType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.AVA", /* tp_name */
|
|
sizeof(AVA), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)AVA_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
(cmpfunc)AVA_compare, /* tp_compare */
|
|
(reprfunc)AVA_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
AVA_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
AVA_methods, /* tp_methods */
|
|
AVA_members, /* tp_members */
|
|
AVA_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)AVA_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
AVA_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
AVA_new_from_CERTAVA(CERTAVA *ava)
|
|
{
|
|
AVA *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (AVA *) AVAType.tp_new(&AVAType, NULL, NULL)) == NULL)
|
|
return NULL;
|
|
|
|
if ((self->ava = (CERTAVA*) PORT_ArenaZNew(self->arena, CERTAVA)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if (SECITEM_CopyItem(NULL, &self->ava->type, &ava->type) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
self->ava->type.type = siDEROID; /* NSS often fails to set this so force it */
|
|
|
|
if (SECITEM_CopyItem(NULL, &self->ava->value, &ava->value) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =============================== RDN Class ================================ */
|
|
/* ========================================================================== */
|
|
|
|
/*
|
|
* Note: CERT_AddAVA, CERT_AddRDN, CERT_CompareRDN, CERT_CopyRDN, CERT_CreateName
|
|
* CERT_CreateRDN, CERT_DestroyRDN are defined in cert.h
|
|
*
|
|
* But only CERT_AddRDN, CERT_CopyRDN, CERT_CreateName, CERT_CreateRDN
|
|
* are exported by nss.def
|
|
*
|
|
* That means CERT_AddAVA, CERT_CompareRDN, CERT_DestroyRDN
|
|
* are defined as public but aren't. Note CERT_DestroyRDN has no implementation.
|
|
*/
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef RDN_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef RDN_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
/*
|
|
* Compares two CERTRDN's, returns -1 if a < b, 0 if a == b, 1 if a > b
|
|
* If error, returns -2
|
|
*/
|
|
static int
|
|
CERTRDN_compare(CERTRDN *a, CERTRDN *b)
|
|
{
|
|
SECComparison cmp_result;
|
|
int a_len, b_len;
|
|
CERTAVA **a_avas, *a_ava;
|
|
CERTAVA **b_avas, *b_ava;
|
|
|
|
if (a == NULL && b == NULL) return 0;
|
|
if (a == NULL && b != NULL) return -1;
|
|
if (a != NULL && b == NULL) return 1;
|
|
|
|
a_len = CERTRDN_ava_count(a);
|
|
b_len = CERTRDN_ava_count(b);
|
|
|
|
if (a_len < b_len) return -1;
|
|
if (a_len > b_len) return 1;
|
|
|
|
for (a_avas = a->avas, b_avas = b->avas;
|
|
a_avas && (a_ava = *a_avas) && b_avas && (b_ava = *b_avas);
|
|
a_avas++, b_avas++) {
|
|
if ((cmp_result = CERTAVA_compare(a_ava, b_ava)) != 0) {
|
|
return cmp_result;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
RDN_compare(RDN *self, RDN *other)
|
|
{
|
|
int cmp_result;
|
|
|
|
if (!PyRDN_Check(other)) {
|
|
PyErr_SetString(PyExc_TypeError, "Bad type, must be RDN");
|
|
return -1;
|
|
}
|
|
|
|
cmp_result = CERTRDN_compare(self->rdn, other->rdn);
|
|
if (cmp_result == -2) {
|
|
return -1;
|
|
}
|
|
return cmp_result;
|
|
}
|
|
|
|
PyDoc_STRVAR(RDN_has_key_doc,
|
|
"has_key(arg) -> bool\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
arg : string or integer\n\
|
|
canonical name (e.g. 'cn') or oid dotted-decimal or\n\
|
|
SEC_OID_* enumeration constant\n\
|
|
\n\
|
|
return True if RDN has an AVA whose oid can be identified by arg.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
RDN_has_key(RDN *self, PyObject *args)
|
|
{
|
|
PyObject *arg;
|
|
int oid_tag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:has_key",
|
|
&arg))
|
|
return NULL;
|
|
|
|
oid_tag = get_oid_tag_from_object(arg);
|
|
if (oid_tag == SEC_OID_UNKNOWN || oid_tag == -1) {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
if (CERTRDN_has_tag(self->rdn, oid_tag)) {
|
|
Py_RETURN_TRUE;
|
|
} else {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
}
|
|
|
|
/* =========================== Sequence Protocol ============================ */
|
|
|
|
static Py_ssize_t
|
|
CERTRDN_ava_count(CERTRDN *rdn)
|
|
{
|
|
Py_ssize_t count;
|
|
CERTAVA **avas;
|
|
|
|
if (!rdn) return 0;
|
|
for (avas = rdn->avas, count = 0; *avas; avas++, count++);
|
|
|
|
return count;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
RDN_length(RDN *self)
|
|
{
|
|
return CERTRDN_ava_count(self->rdn);
|
|
}
|
|
|
|
static PyObject *
|
|
RDN_item(RDN *self, register Py_ssize_t i)
|
|
{
|
|
Py_ssize_t count = 0;
|
|
CERTAVA **avas;
|
|
|
|
if (i < 0 || !self->rdn || self->rdn->avas == NULL) {
|
|
PyErr_SetString(PyExc_IndexError, "RDN index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
for (avas = self->rdn->avas, count = 0; *avas && count < i; avas++, count++);
|
|
|
|
if (!*avas) {
|
|
PyErr_SetString(PyExc_IndexError, "RDN index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
return AVA_new_from_CERTAVA(*avas);
|
|
}
|
|
|
|
|
|
static bool
|
|
CERTRDN_has_tag(CERTRDN *rdn, int tag)
|
|
{
|
|
CERTAVA **avas;
|
|
CERTAVA *ava = NULL;
|
|
|
|
if (!rdn) return false;
|
|
for (avas = rdn->avas; avas && (ava = *avas); avas++) {
|
|
int ava_tag = CERT_GetAVATag(ava);
|
|
if (tag == ava_tag) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTRDN_get_matching_tag_list(CERTRDN *rdn, int tag)
|
|
{
|
|
PyObject *list = NULL;
|
|
PyObject *py_ava = NULL;
|
|
CERTAVA **avas, *ava;
|
|
|
|
if ((list = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!rdn) {
|
|
return list;
|
|
}
|
|
|
|
for (avas = rdn->avas; avas && (ava = *avas); avas++) {
|
|
int ava_tag = CERT_GetAVATag(ava);
|
|
if (tag == ava_tag) {
|
|
if ((py_ava = AVA_new_from_CERTAVA(ava)) == NULL) {
|
|
Py_DECREF(list);
|
|
return NULL;
|
|
}
|
|
PyList_Append(list, py_ava);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
static PyObject*
|
|
RDN_subscript(RDN *self, PyObject* item)
|
|
{
|
|
PyObject* result;
|
|
|
|
if (PyIndex_Check(item)) {
|
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
return NULL;
|
|
if (i < 0)
|
|
i += RDN_length(self);
|
|
return RDN_item(self, i);
|
|
} else if (PySlice_Check(item)) {
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
|
PyObject* py_ava;
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, RDN_length(self),
|
|
&start, &stop, &step, &slicelength) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (slicelength <= 0) {
|
|
return PyList_New(0);
|
|
} else {
|
|
result = PyList_New(slicelength);
|
|
if (!result) return NULL;
|
|
|
|
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
|
|
/* We don't need to bump the ref count because RDN_item
|
|
* returns a new object */
|
|
py_ava = RDN_item(self, cur);
|
|
if (PyList_SetItem(result, i, py_ava) == -1) {
|
|
Py_DECREF(result);
|
|
return NULL;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
} else if (PyString_Check(item) || PyUnicode_Check(item) || PySecItem_Check(item)) {
|
|
int oid_tag;
|
|
|
|
if ((oid_tag = get_oid_tag_from_object(item)) == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
if (oid_tag == SEC_OID_UNKNOWN) {
|
|
if (PyString_Check(item) || PyUnicode_Check(item)) {
|
|
char *name = PyString_AsString(item);
|
|
PyErr_Format(PyExc_KeyError, "oid name unknown: \"%s\"", name);
|
|
return NULL;
|
|
} else {
|
|
PyErr_SetString(PyExc_KeyError, "oid unknown");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if ((result = CERTRDN_get_matching_tag_list(self->rdn, oid_tag)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PyList_Size(result) == 0) {
|
|
Py_DECREF(result);
|
|
if (PyString_Check(item) || PyUnicode_Check(item)) {
|
|
char *name = PyString_AsString(item);
|
|
PyErr_Format(PyExc_KeyError, "oid name not found: \"%s\"", name);
|
|
return NULL;
|
|
} else {
|
|
PyErr_SetString(PyExc_KeyError, "oid not found");
|
|
return NULL;
|
|
}
|
|
} else {
|
|
return result;
|
|
}
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"indices must be integers or strings, not %.200s",
|
|
item->ob_type->tp_name);
|
|
return NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
RDN_repr(RDN *self)
|
|
{
|
|
return CERTRDN_to_pystr(self->rdn);
|
|
}
|
|
|
|
static PyMethodDef RDN_methods[] = {
|
|
{"has_key", (PyCFunction)RDN_has_key, METH_VARARGS, RDN_has_key_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
RDN_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
RDN *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (RDN *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->rdn = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
RDN_dealloc(RDN* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(RDN_doc,
|
|
"An object representing an X501 Relative Distinguished Name (e.g. RDN).\n\
|
|
\n\
|
|
RDN objects contain an ordered list of `AVA` objects. \n\
|
|
\n\
|
|
Examples::\n\
|
|
\n\
|
|
RDN()\n\
|
|
RDN(nss.AVA('cn', 'www.redhat.com'))\n\
|
|
RDN([ava0, ava1])\n\
|
|
\n\
|
|
The RDN object constructor may be invoked with zero or more\n\
|
|
`AVA` objects, or you may optionally pass a list or tuple of `AVA`\n\
|
|
objects.\n\
|
|
\n\
|
|
RDN objects contain an ordered list of `AVA` objects. The\n\
|
|
RDN object has both sequence and mapping behaviors with respect to\n\
|
|
the AVA's they contain. Thus you can index an AVA by position, by\n\
|
|
name, or by SecItem (if it's an OID). You can iterate over the list,\n\
|
|
get it's length or take a slice.\n\
|
|
\n\
|
|
If you index by string the string may be either a canonical name for\n\
|
|
the AVA type (e.g. 'cn') or the dotted-decimal notation for the OID\n\
|
|
(e.g. 2.5.4.3). There may be multiple AVA's in a RDN whose type matches\n\
|
|
(e.g. OU=engineering+OU=boston). It is not common to have more than\n\
|
|
one AVA in a RDN with the same type. However because of the possiblity\n\
|
|
of being multi-valued when indexing by type a list is always returned\n\
|
|
containing the matching AVA's. Thus::\n\
|
|
\n\
|
|
rdn = nss.RDN(nss.AVA('OU', 'engineering'))\n\
|
|
rdn['ou']\n\
|
|
returns [AVA('OU=engineering')\n\
|
|
\n\
|
|
rdn = nss.RDN(nss.AVA('OU', 'engineering'), nss.AVA('OU', 'boston'))\n\
|
|
rdn['ou']\n\
|
|
returns [AVA('OU=boston'), AVA('OU=engineering')]\n\
|
|
\n\
|
|
Examples::\n\
|
|
\n\
|
|
rdn = nss.RDN(nss.AVA('cn', 'www.redhat.com'))\n\
|
|
str(rdn)\n\
|
|
returns 'CN=www.redhat.com'\n\
|
|
rdn[0]\n\
|
|
returns an `AVA` object with the value C=US\n\
|
|
rdn['cn']\n\
|
|
returns a list comprised of an `AVA` object with the value CN=www.redhat.com\n\
|
|
rdn['2.5.4.3']\n\
|
|
returns a list comprised of an `AVA` object with the value CN=www.redhat.com\n\
|
|
because 2.5.4.3 is the dotted-decimal OID for common name (i.e. cn)\n\
|
|
rdn.has_key('cn')\n\
|
|
returns True because the RDN has a common name RDN\n\
|
|
rdn.has_key('2.5.4.3')\n\
|
|
returns True because the RDN has a common name AVA\n\
|
|
because 2.5.4.3 is the dotted-decimal OID for common name (i.e. cn)\n\
|
|
len(rdn)\n\
|
|
returns 1 because there is one `AVA` object in it\n\
|
|
list(rdn)\n\
|
|
returns a list of each `AVA` object in it\n\
|
|
\n\
|
|
");
|
|
|
|
static int
|
|
RDN_init(RDN *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
PyObject *sequence, *item;
|
|
Py_ssize_t sequence_len, i;
|
|
AVA *py_ava;
|
|
CERTAVA *ava_arg[MAX_AVAS+1]; /* +1 for NULL terminator */
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (PyTuple_GET_SIZE(args) > 0) {
|
|
sequence = PyTuple_GetItem(args, 0);
|
|
if (!(PyTuple_Check(sequence) || PyList_Check(sequence))) {
|
|
sequence = args;
|
|
}
|
|
sequence_len = PySequence_Length(sequence);
|
|
if (sequence_len > MAX_AVAS) {
|
|
PyErr_Format(PyExc_ValueError, "to many AVA items, maximum is %d, received %d",
|
|
MAX_AVAS-1, sequence_len);
|
|
return -1;
|
|
}
|
|
for (i = 0; i < sequence_len && i < MAX_AVAS; i++) {
|
|
item = PySequence_ITEM(sequence, i);
|
|
if (PyAVA_Check(item)) {
|
|
py_ava = (AVA *)item;
|
|
if ((ava_arg[i] = CERT_CopyAVA(self->arena, py_ava->ava)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_DECREF(item);
|
|
return -1;
|
|
}
|
|
Py_DECREF(item);
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError, "item %d must be an AVA object, not %.200s",
|
|
i, Py_TYPE(item)->tp_name);
|
|
Py_DECREF(item);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
for (; i < MAX_AVAS+1; i++) ava_arg[i] = NULL;
|
|
|
|
if ((self->rdn = CERT_CreateRDN(self->arena,
|
|
ava_arg[0], ava_arg[1], ava_arg[2], ava_arg[3],
|
|
ava_arg[4], ava_arg[5], ava_arg[6], ava_arg[7],
|
|
ava_arg[8], ava_arg[9], ava_arg[10])) == NULL) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PySequenceMethods RDN_as_sequence = {
|
|
(lenfunc)RDN_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)RDN_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyMappingMethods RDN_as_mapping = {
|
|
(lenfunc)RDN_length, /* mp_length */
|
|
(binaryfunc)RDN_subscript, /* mp_subscript */
|
|
0, /* mp_ass_subscript */
|
|
};
|
|
|
|
static PyTypeObject RDNType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.RDN", /* tp_name */
|
|
sizeof(RDN), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)RDN_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
(cmpfunc)RDN_compare, /* tp_compare */
|
|
(reprfunc)RDN_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&RDN_as_sequence, /* tp_as_sequence */
|
|
&RDN_as_mapping, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
RDN_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
RDN_methods, /* tp_methods */
|
|
RDN_members, /* tp_members */
|
|
RDN_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)RDN_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
RDN_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
RDN_new_from_CERTRDN(CERTRDN *rdn)
|
|
{
|
|
RDN *self = NULL;
|
|
int i;
|
|
CERTAVA *ava_arg[MAX_AVAS+1]; /* +1 for NULL terminator */
|
|
CERTAVA **avas, *ava;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (RDN *) RDNType.tp_new(&RDNType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
i = 0;
|
|
if (rdn) {
|
|
for (avas = rdn->avas; i < MAX_AVAS && avas && (ava = *avas); avas++, i++) {
|
|
if ((ava_arg[i] = CERT_CopyAVA(self->arena, ava)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (; i < MAX_AVAS+1; i++) ava_arg[i] = NULL;
|
|
|
|
if ((self->rdn = CERT_CreateRDN(self->arena,
|
|
ava_arg[0], ava_arg[1], ava_arg[2], ava_arg[3],
|
|
ava_arg[4], ava_arg[5], ava_arg[6], ava_arg[7],
|
|
ava_arg[8], ava_arg[9], ava_arg[10])) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =============================== DN Class ================================= */
|
|
/* ========================================================================== */
|
|
|
|
/*
|
|
* NSS WART
|
|
*
|
|
* CERT_CopyRDN() does not return a new CERTRDN, requires calling CERT_CreateRDN()
|
|
*
|
|
* CERT_CreateName() does not copy it's rdn arguments, must call CERT_CopyRDN()
|
|
*
|
|
* CERT_CreateName() does not allow you to pass in an arena, it creates one
|
|
* and stores it internally. But to call CERT_CreateName() you have to call
|
|
* CERT_CopyRDN() which requires an arena. This means a CERTName object has to
|
|
* have 2 arenas when one would have sufficed, it also means more bookkeeping
|
|
* to manage the second unnecessary arena.
|
|
*
|
|
* CERT_CopyAVA() doesn't return SECStatus unlike other copy routines.
|
|
*/
|
|
|
|
/*
|
|
* All these are defined in cert.h and all are exported in nss.def
|
|
*
|
|
* CERT_AsciiToName
|
|
* CERT_NameToAscii
|
|
* CERT_NameToAsciiInvertible
|
|
* CERT_CreateName
|
|
* CERT_CopyName
|
|
* CERT_DestroyName
|
|
* CERT_AddRDN
|
|
* CERT_CompareName
|
|
* CERT_FormatName
|
|
* CERT_GetCertEmailAddress
|
|
* CERT_GetCommonName
|
|
* CERT_GetCountryName
|
|
* CERT_GetLocalityName
|
|
* CERT_GetStateName
|
|
* CERT_GetOrgName
|
|
* CERT_GetOrgUnitName
|
|
* CERT_GetDomainComponentName
|
|
* CERT_GetCertUid
|
|
*/
|
|
|
|
static bool
|
|
CERTName_has_tag(CERTName *name, int tag)
|
|
{
|
|
CERTRDN **rdns, *rdn;
|
|
CERTAVA **avas, *ava;
|
|
|
|
if (!name) return false;
|
|
for (rdns = name->rdns; rdns && (rdn = *rdns); rdns++) {
|
|
for (avas = rdn->avas; avas && (ava = *avas); avas++) {
|
|
int ava_tag = CERT_GetAVATag(ava);
|
|
if (tag == ava_tag) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static PyObject *
|
|
CERTName_get_matching_tag_list(CERTName *name, int tag)
|
|
{
|
|
PyObject *list = NULL;
|
|
PyObject *py_rdn = NULL;
|
|
CERTRDN **rdns, *rdn;
|
|
CERTAVA **avas, *ava;
|
|
|
|
if ((list = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!name) {
|
|
return list;
|
|
}
|
|
|
|
for (rdns = name->rdns; rdns && (rdn = *rdns); rdns++) {
|
|
for (avas = rdn->avas; avas && (ava = *avas); avas++) {
|
|
int ava_tag = CERT_GetAVATag(ava);
|
|
if (tag == ava_tag) {
|
|
if ((py_rdn = RDN_new_from_CERTRDN(rdn)) == NULL) {
|
|
Py_DECREF(list);
|
|
return NULL;
|
|
}
|
|
PyList_Append(list, py_rdn);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static PyObject*
|
|
DN_subscript(DN *self, PyObject* item)
|
|
{
|
|
PyObject* result = NULL;
|
|
|
|
if (PyIndex_Check(item)) {
|
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
return NULL;
|
|
if (i < 0)
|
|
i += DN_length(self);
|
|
return DN_item(self, i);
|
|
} else if (PySlice_Check(item)) {
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
|
PyObject* py_ava;
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, DN_length(self),
|
|
&start, &stop, &step, &slicelength) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (slicelength <= 0) {
|
|
return PyList_New(0);
|
|
} else {
|
|
result = PyList_New(slicelength);
|
|
if (!result) return NULL;
|
|
|
|
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
|
|
/* We don't need to bump the ref count because RDN_item
|
|
* returns a new object */
|
|
py_ava = DN_item(self, cur);
|
|
if (PyList_SetItem(result, i, py_ava) == -1) {
|
|
Py_DECREF(result);
|
|
return NULL;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
} else if (PyString_Check(item) || PyUnicode_Check(item) || PySecItem_Check(item)) {
|
|
int oid_tag;
|
|
|
|
if ((oid_tag = get_oid_tag_from_object(item)) == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
if (oid_tag == SEC_OID_UNKNOWN) {
|
|
if (PyString_Check(item) || PyUnicode_Check(item)) {
|
|
char *name = PyString_AsString(item);
|
|
PyErr_Format(PyExc_KeyError, "oid name unknown: \"%s\"", name);
|
|
return NULL;
|
|
} else {
|
|
PyErr_SetString(PyExc_KeyError, "oid unknown");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if ((result = CERTName_get_matching_tag_list(&self->name, oid_tag)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PyList_Size(result) == 0) {
|
|
Py_DECREF(result);
|
|
if (PyString_Check(item) || PyUnicode_Check(item)) {
|
|
char *name = PyString_AsString(item);
|
|
PyErr_Format(PyExc_KeyError, "oid name not found: \"%s\"", name);
|
|
return NULL;
|
|
} else {
|
|
PyErr_SetString(PyExc_KeyError, "oid not found");
|
|
return NULL;
|
|
}
|
|
} else {
|
|
return result;
|
|
}
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"indices must be integers or strings, not %.200s",
|
|
item->ob_type->tp_name);
|
|
return NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
PyDoc_STRVAR(DN_has_key_doc,
|
|
"has_key(arg) -> bool\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
arg : string or integer\n\
|
|
canonical name (e.g. 'cn') or oid dotted-decimal or\n\
|
|
SEC_OID_* enumeration constant\n\
|
|
\n\
|
|
return True if Name has an AVA whose oid can be identified by arg.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
DN_has_key(DN *self, PyObject *args)
|
|
{
|
|
PyObject *arg;
|
|
int oid_tag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:has_key",
|
|
&arg))
|
|
return NULL;
|
|
|
|
oid_tag = get_oid_tag_from_object(arg);
|
|
if (oid_tag == SEC_OID_UNKNOWN || oid_tag == -1) {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
if (CERTName_has_tag(&self->name, oid_tag)) {
|
|
Py_RETURN_TRUE;
|
|
} else {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
}
|
|
|
|
/* =========================== Sequence Protocol ============================ */
|
|
|
|
static Py_ssize_t
|
|
CERTName_rdn_count(CERTName *name)
|
|
{
|
|
Py_ssize_t count = 0;
|
|
CERTRDN **rdns;
|
|
|
|
for (rdns = name->rdns, count = 0; *rdns; rdns++, count++);
|
|
|
|
return count;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
DN_length(DN *self)
|
|
{
|
|
return CERTName_rdn_count(&self->name);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_item(DN *self, register Py_ssize_t i)
|
|
{
|
|
Py_ssize_t count = 0;
|
|
CERTRDN **rdns;
|
|
|
|
if (i < 0 || self->name.rdns == NULL) {
|
|
PyErr_SetString(PyExc_IndexError, "DN index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
for (rdns = self->name.rdns, count = 0; *rdns && count < i; rdns++, count++);
|
|
|
|
if (!*rdns) {
|
|
PyErr_SetString(PyExc_IndexError, "DN index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
return RDN_new_from_CERTRDN(*rdns);
|
|
}
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
DN_get_email_address(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetCertEmailAddress(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_common_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetCommonName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_country_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetCountryName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_locality_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetLocalityName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_state_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetStateName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_org_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetOrgName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_org_unit_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetOrgUnitName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_domain_component_name(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetDomainComponentName(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static PyObject *
|
|
DN_get_cert_uid(DN *self, void *closure)
|
|
{
|
|
char *value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((value = CERT_GetCertUid(&self->name)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return PyString_FromString(value);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef DN_getseters[] = {
|
|
{"email_address", (getter)DN_get_email_address, (setter)NULL,
|
|
"Returns the email address member as a string. Returns None if not found.", NULL},
|
|
{"common_name", (getter)DN_get_common_name, (setter)NULL,
|
|
"Returns the common name member (i.e. CN) as a string. Returns None if not found.", NULL},
|
|
{"country_name", (getter)DN_get_country_name, (setter)NULL,
|
|
"Returns the country name member (i.e. C) as a string. Returns None if not found.", NULL},
|
|
{"locality_name", (getter)DN_get_locality_name, (setter)NULL,
|
|
"Returns the locality name member (i.e. L) as a string. Returns None if not found.", NULL},
|
|
{"state_name", (getter)DN_get_state_name, (setter)NULL,
|
|
"Returns the state name member (i.e. ST) as a string. Returns None if not found.", NULL},
|
|
{"org_name", (getter)DN_get_org_name, (setter)NULL,
|
|
"Returns the organization name member (i.e. O) as a string. Returns None if not found.", NULL},
|
|
{"org_unit_name", (getter)DN_get_org_unit_name, (setter)NULL,
|
|
"Returns the organizational unit name member (i.e. OU) as a string. Returns None if not found.", NULL},
|
|
{"dc_name", (getter)DN_get_domain_component_name, (setter)NULL,
|
|
"Returns the domain component name member (i.e. DC) as a string. Returns None if not found.", NULL},
|
|
{"cert_uid", (getter)DN_get_cert_uid, (setter)NULL,
|
|
"Returns the certificate uid member (i.e. UID) as a string. Returns None if not found.", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef DN_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static int
|
|
DN_compare(DN *self, DN *other)
|
|
{
|
|
if (!PyDN_Check(other)) {
|
|
PyErr_SetString(PyExc_TypeError, "Bad type, must be DN");
|
|
return -1;
|
|
}
|
|
|
|
return CERT_CompareName(&self->name, &other->name);
|
|
}
|
|
|
|
PyDoc_STRVAR(DN_add_rdn_doc,
|
|
"add_rdn(rdn) \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
rdn : RDN object\n\
|
|
The rnd to add to the name\n\
|
|
\n\
|
|
Adds a RDN to the name.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
DN_add_rdn(DN *self, PyObject *args)
|
|
{
|
|
RDN *py_rdn;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O!:add_rdn",
|
|
&RDNType, &py_rdn))
|
|
return NULL;
|
|
|
|
if (CERT_AddRDN(&self->name, py_rdn->rdn) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyMethodDef DN_methods[] = {
|
|
{"has_key", (PyCFunction)DN_has_key, METH_VARARGS, DN_has_key_doc},
|
|
{"add_rdn", (PyCFunction)DN_add_rdn, METH_VARARGS, DN_add_rdn_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
DN_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
DN *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (DN *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
memset(&self->name, 0, sizeof(self->name));
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
DN_dealloc(DN* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
CERT_DestroyName(&self->name);
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(DN_doc,
|
|
"An object representing an X501 Distinguished Name (e.g DN).\n\
|
|
\n\
|
|
DN objects contain an ordered list of `RDN` objects.\n\
|
|
\n\
|
|
The DN object constructor may be invoked with a string\n\
|
|
representing an X500 name. Zero or more `RDN` objects, or you may\n\
|
|
optionally pass a list or tuple of `RDN` objects.\n\
|
|
\n\
|
|
Examples::\n\
|
|
\n\
|
|
DN()\n\
|
|
DN('CN=www.redhat.com,OU=Web Operations,O=Red Hat Inc,L=Raleigh,ST=North Carolina,C=US')\n\
|
|
DN(rdn0, ...)\n\
|
|
DN([rdn0, rdn1])\n\
|
|
\n\
|
|
**The string representation of a Distinguished Name (DN) has reverse\n\
|
|
ordering from it's sequential components.**\n\
|
|
\n\
|
|
The ordering is a requirement of the relevant RFC's. When a\n\
|
|
Distinguished Name is rendered as a string it is ordered from most\n\
|
|
specific to least specific. However it's components (RDN's) as a\n\
|
|
sequence are ordered from least specific to most specific.\n\
|
|
\n\
|
|
DN objects contain an ordered list of `RDN` objects. The\n\
|
|
DN object has both sequence and mapping behaviors with respect to\n\
|
|
the RDN's they contain. Thus you can index an RDN by position, by\n\
|
|
name, or by SecItem (if it's an OID). You can iterate over the list,\n\
|
|
get it's length or take a slice.\n\
|
|
\n\
|
|
If you index by string the string may be either a canonical name for\n\
|
|
the RDN type (e.g. 'cn') or the dotted-decimal notation for the OID\n\
|
|
(e.g. 2.5.4.3). There may be multiple RDN's in a DN whose type matches\n\
|
|
(e.g. OU=engineering, OU=boston). It is not common to have more than\n\
|
|
one RDN in a DN with the same type. However because of the possiblity\n\
|
|
of being multi-valued when indexing by type a list is always returned\n\
|
|
containing the matching RDN's. Thus::\n\
|
|
\n\
|
|
dn = nss.DN('OU=engineering')\n\
|
|
dn['ou']\n\
|
|
returns [RDN('OU=engineering')\n\
|
|
\n\
|
|
dn = nss.DN('OU=engineering, OU=boston')\n\
|
|
dn['ou']\n\
|
|
returns [RDN('OU=boston'), RDN('OU=engineering')]\n\
|
|
Note the reverse ordering between string representation and RDN sequencing\n\
|
|
\n\
|
|
Note, if you use properties to access the RDN values (e.g. name.common_name,\n\
|
|
name.org_unit_name) the string value is returned or None if not found.\n\
|
|
If the item was multi-valued then the most appropriate item will be selected\n\
|
|
and returned as a string value.\n\
|
|
\n\
|
|
Note it is not possible to index by oid tag\n\
|
|
(e.g. nss.SEC_OID_AVA_COMMON_NAME) because oid tags are integers and\n\
|
|
it's impossible to distinguish between an integer representing the\n\
|
|
n'th member of the sequence and the integer representing the oid\n\
|
|
tag. In this case positional indexing wins (e.g. rdn[0] means the\n\
|
|
first element).\n\
|
|
\n\
|
|
Examples::\n\
|
|
\n\
|
|
subject_name = 'CN=www.redhat.com,OU=Web Operations,O=Red Hat Inc,L=Raleigh,ST=North Carolina,C=US'\n\
|
|
name = nss.DN(subject_name)\n\
|
|
str(name)\n\
|
|
returns 'CN=www.redhat.com,OU=Web Operations,O=Red Hat Inc,L=Raleigh,ST=North Carolina,C=US'\n\
|
|
name[0]\n\
|
|
returns an `RDN` object with the value C=US\n\
|
|
name['cn']\n\
|
|
returns a list comprised of an `RDN` object with the value CN=www.redhat.com\n\
|
|
name['2.5.4.3']\n\
|
|
returns a list comprised of an `RDN` object with the value CN=www.redhat.com\n\
|
|
because 2.5.4.3 is the dotted-decimal OID for common name (i.e. cn)\n\
|
|
name.common_name\n\
|
|
returns the string www.redhat.com\n\
|
|
common_name is easy shorthand property, it only retuns a single string\n\
|
|
value or None, if it was multi-valued the most appropriate item is selected.\n\
|
|
name.has_key('cn')\n\
|
|
returns True because the DN has a common name RDN\n\
|
|
name.has_key('2.5.4.3')\n\
|
|
returns True because the DN has a common name RDN\n\
|
|
because 2.5.4.3 is the dotted-decimal OID for common name (i.e. cn)\n\
|
|
\n\
|
|
cn_rdn = nss.RDN(nss.AVA('cn', 'www.redhat.com'))\n\
|
|
ou_rdn = nss.RDN(nss.AVA('ou', 'Web Operations'))\n\
|
|
name = nss.DN(cn_rdn)\n\
|
|
name\n\
|
|
is a DN with one RDN (e.g. CN=www.redhat.com)\n\
|
|
len(name)\n\
|
|
returns 1 because there is one RDN in it\n\
|
|
name.add_rdn(ou_rdn)\n\
|
|
name\n\
|
|
name is now a DN with two RDN's (e.g. OU=Web Operations,CN=www.redhat.com)\n\
|
|
len(name)\n\
|
|
returns 2 because there are now two RDN's in it\n\
|
|
list(name)\n\
|
|
returns a list with the two RDN's in it\n\
|
|
name[:]\n\
|
|
same as list(name)\n\
|
|
for rdn in name:\n\
|
|
iterate over each RDN in name\n\
|
|
name = nss.DN(cn_rdn, ou_rdn)\n\
|
|
This is an alternate way to build the above DN\n\
|
|
");
|
|
|
|
static int
|
|
DN_init(DN *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
PyObject *sequence, *item;
|
|
Py_ssize_t sequence_len, i;
|
|
RDN *py_rdn;
|
|
CERTRDN *new_rdn;
|
|
CERTName *cert_name;
|
|
CERTRDN *rdn_arg[MAX_RDNS+1]; /* +1 for NULL terminator */
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
CERT_DestroyName(&self->name);
|
|
|
|
if (PyTuple_GET_SIZE(args) > 0) {
|
|
item = PyTuple_GetItem(args, 0);
|
|
if (PyString_Check(item) || PyUnicode_Check(item)) {
|
|
char *ascii_name;
|
|
|
|
if ((ascii_name = PyString_AsString(item)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (strlen(ascii_name) == 0) goto empty_name;
|
|
|
|
if ((cert_name = CERT_AsciiToName(ascii_name)) == NULL) {
|
|
set_nspr_error("cannot parse X500 name \"%s\"", ascii_name);
|
|
return -1;
|
|
}
|
|
|
|
self->name = *cert_name;
|
|
return 0;
|
|
}
|
|
|
|
if (PyRDN_Check(item)) {
|
|
sequence = args;
|
|
} else if (PyList_Check(item) || PyTuple_Check(item)) {
|
|
sequence = item;
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError, "must be an RDN object or list or tuple of RDN objects, not %.200s",
|
|
Py_TYPE(item)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
sequence_len = PySequence_Length(sequence);
|
|
|
|
if (sequence_len > MAX_RDNS) {
|
|
PyErr_Format(PyExc_ValueError, "to many RDN items, maximum is %d, received %d",
|
|
MAX_RDNS-1, sequence_len);
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < sequence_len && i < MAX_RDNS; i++) {
|
|
item = PySequence_ITEM(sequence, i);
|
|
if (PyRDN_Check(item)) {
|
|
py_rdn = (RDN *)item;
|
|
|
|
if ((new_rdn = CERT_CreateRDN(self->arena, NULL)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_DECREF(item);
|
|
return -1;
|
|
}
|
|
|
|
if (CERT_CopyRDN(self->arena, new_rdn, py_rdn->rdn) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_DECREF(item);
|
|
return -1;
|
|
}
|
|
rdn_arg[i] = new_rdn;
|
|
} else {
|
|
PyErr_Format(PyExc_TypeError, "item %d must be an RDN object, not %.200s",
|
|
i, Py_TYPE(item)->tp_name);
|
|
Py_DECREF(item);
|
|
return -1;
|
|
}
|
|
Py_DECREF(item);
|
|
}
|
|
|
|
for (; i < MAX_RDNS+1; i++) rdn_arg[i] = NULL;
|
|
|
|
if ((cert_name = CERT_CreateName(rdn_arg[0], rdn_arg[1], rdn_arg[2], rdn_arg[3],
|
|
rdn_arg[4], rdn_arg[5], rdn_arg[6], rdn_arg[7],
|
|
rdn_arg[8], rdn_arg[9], rdn_arg[10])) == NULL) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
self->name = *cert_name;
|
|
} else {
|
|
empty_name:
|
|
if ((cert_name = CERT_CreateName(NULL)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
self->name = *cert_name;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
DN_repr(DN *self)
|
|
{
|
|
return CERTName_to_pystr(&self->name);
|
|
}
|
|
|
|
static PySequenceMethods DN_as_sequence = {
|
|
(lenfunc)DN_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)DN_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyMappingMethods DN_as_mapping = {
|
|
(lenfunc)DN_length, /* mp_length */
|
|
(binaryfunc)DN_subscript, /* mp_subscript */
|
|
0, /* mp_ass_subscript */
|
|
};
|
|
|
|
static PyTypeObject DNType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.DN", /* tp_name */
|
|
sizeof(DN), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)DN_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
(cmpfunc)DN_compare, /* tp_compare */
|
|
(reprfunc)DN_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&DN_as_sequence, /* tp_as_sequence */
|
|
&DN_as_mapping, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)DN_repr, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
DN_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
DN_methods, /* tp_methods */
|
|
DN_members, /* tp_members */
|
|
DN_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)DN_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
DN_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
DN_new_from_CERTName(CERTName *name)
|
|
{
|
|
DN *self = NULL;
|
|
PRArenaPool *arena;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (DN *) DNType.tp_new(&DNType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
if (CERT_CopyName(arena, &self->name, name) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =========================== GeneralName Class ============================ */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
GeneralName_get_type_enum(GeneralName *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
return PyInt_FromLong(self->name->type);
|
|
}
|
|
|
|
static PyObject *
|
|
GeneralName_get_type_name(GeneralName *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
return general_name_type_to_pystr(self->name->type);
|
|
}
|
|
|
|
static PyObject *
|
|
GeneralName_get_type_string(GeneralName *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
return CERTGeneralName_type_string_to_pystr(self->name);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef GeneralName_getseters[] = {
|
|
{"type_enum", (getter)GeneralName_get_type_enum, (setter)NULL,
|
|
"Returns the general name type enumerated constant", NULL},
|
|
{"type_name", (getter)GeneralName_get_type_name, (setter)NULL,
|
|
"Returns the general name type enumerated constant as a string", NULL},
|
|
{"type_string", (getter)GeneralName_get_type_string, (setter)NULL,
|
|
"Returns the type of the general name as a string (e.g. \"URI\")", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef GeneralName_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(GeneralName_get_name_doc,
|
|
"get_name(repr_kind=AsString) -> \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsObject\n\
|
|
The general name as a nss.GeneralName object\n\
|
|
AsString\n\
|
|
The general name as a string.\n\
|
|
(e.g. \"http://crl.geotrust.com/crls/secureca.crl\")\n\
|
|
AsTypeString\n\
|
|
The general name type as a string.\n\
|
|
(e.g. \"URI\")\n\
|
|
AsTypeEnum\n\
|
|
The general name type as a general name type enumerated constant.\n\
|
|
(e.g. nss.certURI )\n\
|
|
AsLabeledString\n\
|
|
The general name as a string with it's type prepended.\n\
|
|
(e.g. \"URI: http://crl.geotrust.com/crls/secureca.crl\"\n\
|
|
\n\
|
|
Returns the value of the GeneralName according to the representation type parameter.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
GeneralName_get_name(GeneralName *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"arg1", NULL};
|
|
PyObject *name;
|
|
int repr_kind = AsString;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:get_name", kwlist,
|
|
&repr_kind))
|
|
return NULL;
|
|
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
switch(repr_kind) {
|
|
case AsObject:
|
|
Py_INCREF(self);
|
|
name = (PyObject *)self;
|
|
break;
|
|
case AsString:
|
|
name = CERTGeneralName_to_pystr(self->name);
|
|
break;
|
|
case AsTypeString:
|
|
name = CERTGeneralName_type_string_to_pystr(self->name);
|
|
break;
|
|
case AsTypeEnum:
|
|
name = PyInt_FromLong(self->name->type);
|
|
break;
|
|
case AsLabeledString:
|
|
name = CERTGeneralName_to_pystr_with_label(self->name);
|
|
break;
|
|
default:
|
|
PyErr_Format(PyExc_ValueError, "Unsupported representation kind (%d)", repr_kind);
|
|
return NULL;
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
static PyMethodDef GeneralName_methods[] = {
|
|
{"get_name", (PyCFunction)GeneralName_get_name, METH_VARARGS|METH_KEYWORDS, GeneralName_get_name_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
GeneralName_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
GeneralName *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (GeneralName *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->name = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
GeneralName_dealloc(GeneralName* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(GeneralName_doc,
|
|
"An object representing a GeneralName or list of GeneralNames.\n\
|
|
\n\
|
|
");
|
|
|
|
static int
|
|
GeneralName_init(GeneralName *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"sec_item", NULL};
|
|
SecItem *py_sec_item;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:GeneralName", kwlist,
|
|
&SecItemType, &py_sec_item))
|
|
return -1;
|
|
|
|
if ((self->name = CERT_DecodeGeneralName(self->arena, &py_sec_item->item, NULL)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
GeneralName_repr(GeneralName *self)
|
|
{
|
|
PyObject *result = NULL;
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
if ((result = CERTGeneralName_to_pystr_with_label(self->name)) == NULL) {
|
|
result = PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
GeneralName_length(GeneralName *self)
|
|
{
|
|
if (!self->name) {
|
|
PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
return -1;
|
|
}
|
|
|
|
return CERTGeneralName_list_count(self->name);
|
|
}
|
|
|
|
static PyObject *
|
|
GeneralName_item(GeneralName *self, register Py_ssize_t i)
|
|
{
|
|
CERTGeneralName *head, *cur;
|
|
Py_ssize_t index;
|
|
|
|
if (!self->name) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
index = 0;
|
|
cur = head = self->name;
|
|
do {
|
|
cur = CERT_GetNextGeneralName(cur);
|
|
if (i == index) {
|
|
return GeneralName_new_from_CERTGeneralName(cur);
|
|
}
|
|
index++;
|
|
} while (cur != head);
|
|
|
|
PyErr_SetString(PyExc_IndexError, "GeneralName index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
static PySequenceMethods GeneralName_as_sequence = {
|
|
(lenfunc)GeneralName_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)GeneralName_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyTypeObject GeneralNameType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.GeneralName", /* tp_name */
|
|
sizeof(GeneralName), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)GeneralName_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)GeneralName_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&GeneralName_as_sequence, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
GeneralName_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
GeneralName_methods, /* tp_methods */
|
|
GeneralName_members, /* tp_members */
|
|
GeneralName_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)GeneralName_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
0, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
GeneralName_new_from_CERTGeneralName(CERTGeneralName *name)
|
|
{
|
|
GeneralName *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (GeneralName *) GeneralName_new(&GeneralNameType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* NSS WART
|
|
* There is no public API to create a CERTGeneralName, copy it, or free it.
|
|
* You don't know what arena was used to create the general name.
|
|
* GeneralNames are linked in a list, this makes it difficult for a
|
|
* general name to exist independently, it would have been better if there
|
|
* was a list container independent general names could be placed in,
|
|
* then you wouldn't have to worry about the link fields in each independent name.
|
|
*/
|
|
|
|
if (CERT_CopyGeneralName(self->arena, &self->name, name) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_get_default_certdb_doc,
|
|
"get_default_certdb()\n\
|
|
\n\
|
|
Returns the default certificate database as a CertDB object\n\
|
|
");
|
|
static PyObject *
|
|
cert_get_default_certdb(PyObject *self, PyObject *args)
|
|
{
|
|
CERTCertDBHandle *cert_handle;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((cert_handle = CERT_GetDefaultCertDB()) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return CertDB_new_from_CERTCertDBHandle(cert_handle);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_get_cert_nicknames_doc,
|
|
"get_cert_nicknames(certdb, what, [user_data1, ...]) -> name0, ...\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
certdb : CertDB object\n\
|
|
CertDB certificate database object\n\
|
|
what : integer\n\
|
|
one of:\n\
|
|
- SEC_CERT_NICKNAMES_ALL\n\
|
|
- SEC_CERT_NICKNAMES_USER\n\
|
|
- SEC_CERT_NICKNAMES_SERVER\n\
|
|
- SEC_CERT_NICKNAMES_CA\n\
|
|
user_dataN : object\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Returns a tuple of the nicknames of the certificates in a specified\n\
|
|
certificate database.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_get_cert_nicknames(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 2;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
int what;
|
|
CertDB *py_certdb = NULL;
|
|
CERTCertNicknames *cert_nicknames = NULL;
|
|
PyObject *py_nicknames = NULL;
|
|
PyObject *py_nickname = NULL;
|
|
int i, len;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "O!i:get_cert_nicknames",
|
|
&CertDBType, &py_certdb, &what)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((cert_nicknames = CERT_GetCertNicknames(py_certdb->handle, what, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
len = cert_nicknames->numnicknames;
|
|
if ((py_nicknames = PyTuple_New(len)) == NULL) {
|
|
CERT_FreeNicknames(cert_nicknames);
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if ((py_nickname = PyString_FromString(cert_nicknames->nicknames[i])) == NULL) {
|
|
CERT_FreeNicknames(cert_nicknames);
|
|
return NULL;
|
|
}
|
|
PyTuple_SetItem(py_nicknames, i, py_nickname);
|
|
}
|
|
|
|
CERT_FreeNicknames(cert_nicknames);
|
|
|
|
return py_nicknames;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_hash_buf_doc,
|
|
"hash_buf(hash_alg, data) --> digest\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
hash_alg : int\n\
|
|
hash algorithm enumeration (SEC_OID_*)\n\
|
|
e.g.: SEC_OID_MD5, SEC_OID_SHA1, SEC_OID_SHA256, SEC_OID_SHA512, etc.\n\
|
|
data : buffer or string\n\
|
|
buffer the digest will be computed for\n\
|
|
\n\
|
|
Computes a digest according to the hash_alg type.\n\
|
|
Return the digest data as buffer object.\n\
|
|
\n\
|
|
Note, if a hexidecimal string representation is desired then pass\n\
|
|
result to data_to_hex()\n\
|
|
");
|
|
static PyObject *
|
|
pk11_hash_buf(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long hash_alg;
|
|
unsigned char *in_data = NULL;
|
|
Py_ssize_t in_data_len = 0;
|
|
unsigned int hash_len;
|
|
PyObject *py_out_buf = NULL;
|
|
void *out_buf = NULL;
|
|
Py_ssize_t out_buf_len;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "kt#:hash_buf",
|
|
&hash_alg, &in_data, &in_data_len)) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((hash_len = HASH_ResultLenByOidTag(hash_alg)) == 0) {
|
|
return set_nspr_error("unable to determine resulting hash length for hash_alg = %s",
|
|
oid_tag_str(hash_alg));
|
|
}
|
|
|
|
out_buf_len = hash_len;
|
|
|
|
if ((py_out_buf = PyString_FromStringAndSize(NULL, out_buf_len)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((out_buf = PyString_AsString(py_out_buf)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PK11_HashBuf(hash_alg, out_buf, in_data, in_data_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return py_out_buf;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_md5_digest_doc,
|
|
"md5_digest(data) --> digest\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : buffer or string\n\
|
|
buffer the digest will be computed for\n\
|
|
\n\
|
|
Returns 16 octet MD5 digest data as buffer object.\n\
|
|
\n\
|
|
Note, if a hexidecimal string representation is desired then pass\n\
|
|
result to data_to_hex()\n\
|
|
");
|
|
static PyObject *
|
|
pk11_md5_digest(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned char *in_data = NULL;
|
|
Py_ssize_t in_data_len = 0;
|
|
PyObject *py_out_buf = NULL;
|
|
void *out_buf;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "t#:md5_digest", &in_data, &in_data_len)) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_out_buf = PyString_FromStringAndSize(NULL, MD5_LENGTH)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((out_buf = PyString_AsString(py_out_buf)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PK11_HashBuf(SEC_OID_MD5, out_buf, in_data, in_data_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return py_out_buf;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_sha1_digest_doc,
|
|
"sha1_digest(data) --> digest\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : buffer or string\n\
|
|
buffer the digest will be computed for\n\
|
|
\n\
|
|
Returns 20 octet SHA1 digest data as buffer object.\n\
|
|
\n\
|
|
Note, if a hexidecimal string representation is desired then pass\n\
|
|
result to data_to_hex()\n\
|
|
");
|
|
static PyObject *
|
|
pk11_sha1_digest(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned char *in_data = NULL;
|
|
Py_ssize_t in_data_len = 0;
|
|
PyObject *py_out_buf = NULL;
|
|
void *out_buf;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "t#:sha1_digest", &in_data, &in_data_len)) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_out_buf = PyString_FromStringAndSize(NULL, SHA1_LENGTH)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((out_buf = PyString_AsString(py_out_buf)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PK11_HashBuf(SEC_OID_SHA1, out_buf, in_data, in_data_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return py_out_buf;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_sha256_digest_doc,
|
|
"sha256_digest(data) --> digest\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : buffer or string\n\
|
|
buffer the digest will be computed for\n\
|
|
\n\
|
|
Returns 32 octet SHA256 digest data as buffer object.\n\
|
|
\n\
|
|
Note, if a hexidecimal string representation is desired then pass\n\
|
|
result to data_to_hex()\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_sha256_digest(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned char *in_data = NULL;
|
|
Py_ssize_t in_data_len = 0;
|
|
PyObject *py_out_buf = NULL;
|
|
void *out_buf;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "t#:sha256_digest", &in_data, &in_data_len)) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_out_buf = PyString_FromStringAndSize(NULL, SHA256_LENGTH)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((out_buf = PyString_AsString(py_out_buf)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PK11_HashBuf(SEC_OID_SHA256, out_buf, in_data, in_data_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return py_out_buf;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_sha512_digest_doc,
|
|
"sha512_digest(data) --> digest\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : buffer or string\n\
|
|
buffer the digest will be computed for\n\
|
|
\n\
|
|
Returns 64 octet SHA512 digest data as buffer object.\n\
|
|
\n\
|
|
Note, if a hexidecimal string representation is desired then pass\n\
|
|
result to data_to_hex()\n\
|
|
");
|
|
static PyObject *
|
|
pk11_sha512_digest(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned char *in_data = NULL;
|
|
Py_ssize_t in_data_len = 0;
|
|
PyObject *py_out_buf = NULL;
|
|
void *out_buf;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "t#:sha512_digest", &in_data, &in_data_len)) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_out_buf = PyString_FromStringAndSize(NULL, SHA512_LENGTH)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((out_buf = PyString_AsString(py_out_buf)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (PK11_HashBuf(SEC_OID_SHA512, out_buf, in_data, in_data_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return py_out_buf;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================== PK11Slot Class ============================ */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
PK11_get_slot_name(PK11Slot *self, void *closure)
|
|
{
|
|
char *slot_name = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((slot_name = PK11_GetSlotName(self->slot)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyString_FromString(slot_name);
|
|
}
|
|
|
|
static PyObject *
|
|
PK11_get_token_name(PK11Slot *self, void *closure)
|
|
{
|
|
char *token_name = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((token_name = PK11_GetTokenName(self->slot)) == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyString_FromString(token_name);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef PK11Slot_getseters[] = {
|
|
{"slot_name", (getter)PK11_get_slot_name, (setter)NULL, "slot name", NULL},
|
|
{"token_name", (getter)PK11_get_token_name, (setter)NULL, "token name", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PK11Slot_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
/* ========== Slot Info Functions ========== */
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_hw_doc,
|
|
"is_hw() -> bool\n\
|
|
\n\
|
|
Returns True if the slot is implemented in hardware, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_hw(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsHW(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_present_doc,
|
|
"is_present() -> bool\n\
|
|
\n\
|
|
Returns True if the slot's token present, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_present(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsPresent(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_read_only_doc,
|
|
"is_read_only() -> bool\n\
|
|
\n\
|
|
Returns True if the the slot is read-only, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_read_only(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsReadOnly(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_internal_doc,
|
|
"is_internal() -> bool\n\
|
|
\n\
|
|
Returns True if the the slot is internal, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_internal(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsInternal(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_need_login_doc,
|
|
"need_login() -> bool\n\
|
|
\n\
|
|
Returns True if there are some cryptographic functions that a\n\
|
|
user must be logged in to perform, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_need_login(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_NeedLogin(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_need_user_init_doc,
|
|
"need_user_init() -> bool\n\
|
|
\n\
|
|
Returns True if the slot needs to be logged into by\n\
|
|
the user by providing their pin, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_need_user_init(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_NeedUserInit(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_friendly_doc,
|
|
"is_friendly() -> bool\n\
|
|
\n\
|
|
Returns True if the slot allows certificates to be read\n\
|
|
without logging in to the token, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_friendly(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsFriendly(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_removable_doc,
|
|
"is_removable() -> bool\n\
|
|
\n\
|
|
Returns True if the token is removable, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_removable(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsRemovable(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_has_protected_authentication_path_doc,
|
|
"has_protected_authentication_path() -> bool\n\
|
|
\n\
|
|
Returns True if token has a \"protected authentication path\", whereby\n\
|
|
a user can log into the token without passing a PIN through the\n\
|
|
library, False otherwise. An example might be a token with an\n\
|
|
integrated key pad.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_has_protected_authentication_path(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_ProtectedAuthenticationPath(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_disabled_doc,
|
|
"is_disabled() -> bool\n\
|
|
\n\
|
|
Returns True if the slot is disabled, False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_is_disabled(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsDisabled(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_has_root_certs_doc,
|
|
"has_root_certs() -> bool\n\
|
|
\n\
|
|
Returns True if the slot contains the root certificate , False otherwise.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_has_root_certs(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_HasRootCerts(self->slot))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_get_disabled_reason_doc,
|
|
"get_disabled_reason() -> integer\n\
|
|
\n\
|
|
Returns a diabled reason enumerated constant (i.e. PK11_DIS_*).\n\
|
|
\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* PK11_DIS_NONE\n\
|
|
* PK11_DIS_USER_SELECTED\n\
|
|
* PK11_DIS_COULD_NOT_INIT_TOKEN\n\
|
|
* PK11_DIS_TOKEN_VERIFY_FAILED\n\
|
|
* PK11_DIS_TOKEN_NOT_PRESENT\n\
|
|
\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_get_disabled_reason(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(PK11_GetDisabledReason(self->slot));
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_user_disable_doc,
|
|
"user_disable() \n\
|
|
\n\
|
|
Prevents the slot from being used, and sets disable reason to\n\
|
|
PK11_DIS_USER_SELECTED.\n\
|
|
\n\
|
|
Mechanisms that were on continue to stay on. Therefore, when the slot\n\
|
|
is enabled again via `PK11Slot.user_enable()`, it will remember what\n\
|
|
mechanisms needs to be turned on.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PK11Slot_user_disable(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PK11_UserDisableSlot(self->slot)) {
|
|
return set_nspr_error(_("unable to disable slot"));
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_user_enable_doc,
|
|
"user_enable() \n\
|
|
\n\
|
|
Allow all mechanisms that are ON before `PK11Slot.user_disable()` was\n\
|
|
called to be available again. Sets disable reason to PK11_DIS_NONE.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PK11Slot_user_enable(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PK11_UserEnableSlot(self->slot)) {
|
|
return set_nspr_error(_("unable to enable slot"));
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* ========== Slot Password Management Functions ========== */
|
|
|
|
PyDoc_STRVAR(PK11Slot_is_logged_in_doc,
|
|
"is_logged_in([user_data1, ...]) -> bool\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
user_data1 : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Return True if token is logged in, False otherwise.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PK11Slot_is_logged_in(PK11Slot *self, PyObject *args)
|
|
{
|
|
PyObject *pin_args = args;
|
|
PRBool result;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(pin_args);
|
|
result = PK11_IsLoggedIn(self->slot, pin_args);
|
|
Py_DECREF(pin_args);
|
|
|
|
if (result)
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_authenticate_doc,
|
|
"authenticate(load_certs=False, [user_data1, ...]) -> \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
load_certs : bool\n\
|
|
If True load certificates after authenticating.\n\
|
|
\n\
|
|
Checks to see if token needs to be logged in. If so it invokes the\n\
|
|
password callback (set via `nss.set_password_callback()`) passing the\n\
|
|
optional user_data parameters to the password callback.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PK11Slot_authenticate(PK11Slot *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"load_certs", NULL};
|
|
PyObject *py_load_certs;
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
PRBool load_certs = PR_FALSE;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTupleAndKeywords(parse_args, kwds, "|O!:authenticate", kwlist,
|
|
&PyBool_Type, &py_load_certs)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
load_certs = PyBoolAsPRBool(py_load_certs);
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (PK11_Authenticate(self->slot, load_certs, pin_args) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error("Unable to authenticate");
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_logout_doc,
|
|
"logout()l\n\
|
|
\n\
|
|
Logs a user out of a session destroying any objects\n\
|
|
allocated on their behalf.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_logout(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_Logout(self->slot) != SECSuccess) {
|
|
return set_nspr_error("failed to logout of slot");
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* ========== Slot Mapping Utility Functions ========== */
|
|
|
|
PyDoc_STRVAR(PK11Slot_get_best_wrap_mechanism_doc,
|
|
"get_best_wrap_mechanism() -> mechanism\n\
|
|
\n\
|
|
Find the best key wrap mechanism for this slot.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_get_best_wrap_mechanism(PK11Slot *self, PyObject *args)
|
|
{
|
|
CK_MECHANISM_TYPE mechanism;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
mechanism = PK11_GetBestWrapMechanism(self->slot);
|
|
return PyInt_FromLong(mechanism);
|
|
}
|
|
|
|
|
|
PyDoc_STRVAR(PK11Slot_get_best_key_length_doc,
|
|
"get_best_key_length(mechanism) -> length\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Return the best key length for this slot and mechanism.\n\
|
|
A zero result means that token knows how long the key should be,\n\
|
|
the result is typically used with key_gen(), token_key_gen(), or\n\
|
|
token_key_gen_with_flags()\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_get_best_key_length(PK11Slot *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
int length;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:get_best_key_length", &mechanism))
|
|
return NULL;
|
|
|
|
length = PK11_GetBestKeyLength(self->slot, mechanism);
|
|
return PyInt_FromLong(length);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_key_gen_doc,
|
|
"key_gen(mechanism, sec_param, key_size, [user_data1, ...]) -> PK11SymKey object\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
sec_param : SecItem object or None\n\
|
|
SecItem key parameters. None is also valid.\n\
|
|
key_size : int\n\
|
|
key length (use get_best_key_length())\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Generate a symmetric key.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_key_gen(PK11Slot *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 3;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
unsigned long mechanism;
|
|
int key_size;
|
|
SecItem *py_sec_param;
|
|
PK11SymKey *sym_key;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "kO&i:key_gen",
|
|
&mechanism, SecItemOrNoneConvert, &py_sec_param,
|
|
&key_size)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((sym_key = PK11_KeyGen(self->slot, mechanism, py_sec_param ? &py_sec_param->item : NULL,
|
|
key_size, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
return PyPK11SymKey_new_from_PK11SymKey(sym_key);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_generate_key_pair_doc,
|
|
"generate_key_pair(mechanism, key_params, token, sensitive, [user_data1, ...]) -> public_key, private_key\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
key_params : SecItem object or None\n\
|
|
SecItem key parameters. None is also valid.\n\
|
|
token : bool\n\
|
|
If true the key is a token object otherwise it's a session object.\n\
|
|
sensitive : bool\n\
|
|
If a key is sensitive, certain attributes of the key cannot be\n\
|
|
revealed in plaintext outside the token. It is also more\n\
|
|
expensive to move between tokens.\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Generate a public and private key pair.\n\
|
|
\n\
|
|
Example::\n\
|
|
\n\
|
|
# Generate a DSA key pair\n\
|
|
key_params = nss.KEYPQGParams()\n\
|
|
mechanism = nss.CKM_DSA_KEY_PAIR_GEN\n\
|
|
slot = nss.get_best_slot(mechanism)\n\
|
|
pub_key, priv_key = slot.generate_key_pair(mechanism, key_params, False, False)\n\
|
|
\n\
|
|
# Generate a DSA key pair\n\
|
|
key_params = nss.RSAGenParams()\n\
|
|
mechanism = nss.CKM_RSA_PKCS_KEY_PAIR_GEN\n\
|
|
slot = nss.get_best_slot(mechanism)\n\
|
|
pub_key, priv_key = slot.generate_key_pair(mechanism, key_params, False, False)\n\
|
|
\n\
|
|
");
|
|
static PyObject *
|
|
PK11Slot_generate_key_pair(PK11Slot *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 4;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
unsigned long mechanism;
|
|
int token;
|
|
int sensitive;
|
|
PyObject *py_key_params;
|
|
void *key_params = NULL;
|
|
SECKEYPublicKey *pub_key = NULL;
|
|
SECKEYPrivateKey *priv_key = NULL;
|
|
PyObject *result_tuple = NULL;
|
|
PyObject *py_pub_key = NULL;
|
|
PyObject *py_priv_key = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "kOii:generate_key_pair",
|
|
&mechanism, &py_key_params, &token, &sensitive)) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
switch(mechanism) {
|
|
case CKM_RSA_PKCS_KEY_PAIR_GEN:
|
|
case CKM_RSA_X9_31_KEY_PAIR_GEN:
|
|
if (!PyRSAGenParams_Check(py_key_params)) {
|
|
PyObject *mechanism_name = key_mechanism_type_to_pystr(mechanism);
|
|
|
|
PyErr_Format(PyExc_TypeError, "key_params for %s mechanism must be %.50s, not %.50s",
|
|
mechanism_name ? PyString_AsString(mechanism_name) : "unknown",
|
|
RSAGenParamsType.tp_name, Py_TYPE(py_key_params)->tp_name);
|
|
Py_XDECREF(mechanism_name);
|
|
goto fail;
|
|
}
|
|
key_params = &((RSAGenParams *)py_key_params)->params;
|
|
break;
|
|
case CKM_DSA_KEY_PAIR_GEN:
|
|
if (!PyKEYPQGParams_Check(py_key_params)) {
|
|
PyObject *mechanism_name = key_mechanism_type_to_pystr(mechanism);
|
|
|
|
PyErr_Format(PyExc_TypeError, "key_params for %s mechanism must be %.50s, not %.50s",
|
|
mechanism_name ? PyString_AsString(mechanism_name) : "unknown",
|
|
KEYPQGParamsType.tp_name, Py_TYPE(py_key_params)->tp_name);
|
|
Py_XDECREF(mechanism_name);
|
|
goto fail;
|
|
}
|
|
key_params = &((KEYPQGParams *)py_key_params)->params;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((priv_key = PK11_GenerateKeyPair(self->slot, mechanism, key_params,
|
|
&pub_key,
|
|
token ? PR_TRUE : PR_FALSE,
|
|
sensitive ? PR_TRUE : PR_FALSE,
|
|
pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
set_nspr_error(NULL);
|
|
goto fail;
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_CLEAR(pin_args);
|
|
|
|
if ((py_pub_key = PublicKey_new_from_SECKEYPublicKey(pub_key)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_priv_key = PrivateKey_new_from_SECKEYPrivateKey(priv_key)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((result_tuple = PyTuple_New(2)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
PyTuple_SetItem(result_tuple, 0, py_pub_key);
|
|
PyTuple_SetItem(result_tuple, 1, py_priv_key);
|
|
|
|
return result_tuple;
|
|
|
|
fail:
|
|
Py_XDECREF(parse_args);
|
|
Py_XDECREF(pin_args);
|
|
Py_XDECREF(result_tuple);
|
|
return NULL;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_list_certs_doc,
|
|
"list_certs() -> (`Certificate`, ...)\n\
|
|
\n\
|
|
Returns a tuple of `Certificate` objects found in the slot.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PK11Slot_list_certs(PK11Slot *self, PyObject *args)
|
|
{
|
|
CERTCertList *cert_list = NULL;
|
|
PyObject *tuple = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((cert_list = PK11_ListCertsInSlot(self->slot)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
tuple = CERTCertList_to_tuple(cert_list);
|
|
CERT_DestroyCertList(cert_list);
|
|
return tuple;
|
|
}
|
|
|
|
static PyMethodDef PK11Slot_methods[] = {
|
|
{"is_hw", (PyCFunction)PK11Slot_is_hw, METH_NOARGS, PK11Slot_is_hw_doc},
|
|
{"is_present", (PyCFunction)PK11Slot_is_present, METH_NOARGS, PK11Slot_is_present_doc},
|
|
{"is_read_only", (PyCFunction)PK11Slot_is_read_only, METH_NOARGS, PK11Slot_is_read_only_doc},
|
|
{"is_internal", (PyCFunction)PK11Slot_is_internal, METH_NOARGS, PK11Slot_is_internal_doc},
|
|
{"need_login", (PyCFunction)PK11Slot_need_login, METH_NOARGS, PK11Slot_need_login_doc},
|
|
{"need_user_init", (PyCFunction)PK11Slot_need_user_init, METH_NOARGS, PK11Slot_need_user_init_doc},
|
|
{"is_friendly", (PyCFunction)PK11Slot_is_friendly, METH_NOARGS, PK11Slot_is_friendly_doc},
|
|
{"is_removable", (PyCFunction)PK11Slot_is_removable, METH_NOARGS, PK11Slot_is_removable_doc},
|
|
{"is_logged_in", (PyCFunction)PK11Slot_is_logged_in, METH_NOARGS, PK11Slot_is_logged_in_doc},
|
|
{"has_protected_authentication_path", (PyCFunction)PK11Slot_has_protected_authentication_path, METH_NOARGS, PK11Slot_has_protected_authentication_path_doc},
|
|
{"is_disabled", (PyCFunction)PK11Slot_is_disabled, METH_NOARGS, PK11Slot_is_disabled_doc},
|
|
{"has_root_certs", (PyCFunction)PK11Slot_has_root_certs, METH_NOARGS, PK11Slot_has_root_certs_doc},
|
|
{"get_disabled_reason", (PyCFunction)PK11Slot_get_disabled_reason, METH_NOARGS, PK11Slot_get_disabled_reason_doc},
|
|
{"user_disable", (PyCFunction)PK11Slot_user_disable, METH_NOARGS, PK11Slot_user_disable_doc},
|
|
{"user_enable", (PyCFunction)PK11Slot_user_enable, METH_NOARGS, PK11Slot_user_enable_doc},
|
|
{"authenticate", (PyCFunction)PK11Slot_authenticate, METH_VARARGS|METH_KEYWORDS, PK11Slot_authenticate_doc},
|
|
{"logout", (PyCFunction)PK11Slot_logout, METH_NOARGS, PK11Slot_logout_doc},
|
|
{"get_best_wrap_mechanism", (PyCFunction)PK11Slot_get_best_wrap_mechanism, METH_NOARGS, PK11Slot_get_best_wrap_mechanism_doc},
|
|
{"get_best_key_length", (PyCFunction)PK11Slot_get_best_key_length, METH_VARARGS, PK11Slot_get_best_key_length_doc},
|
|
{"key_gen", (PyCFunction)PK11Slot_key_gen, METH_VARARGS, PK11Slot_key_gen_doc},
|
|
{"generate_key_pair", (PyCFunction)PK11Slot_generate_key_pair, METH_VARARGS, PK11Slot_generate_key_pair_doc},
|
|
{"list_certs", (PyCFunction)PK11Slot_list_certs, METH_NOARGS, PK11Slot_list_certs_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
PK11Slot_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
PK11Slot *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (PK11Slot *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
self->slot = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
PK11Slot_dealloc(PK11Slot* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
/* NSS_Shutdown might have been called before Python deallocates this object */
|
|
if (NSS_IsInitialized()) {
|
|
PK11_FreeSlot(self->slot);
|
|
}
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Slot_doc,
|
|
"An object representing a PKCS #11 Slot");
|
|
|
|
static int
|
|
PK11Slot_init(PK11Slot *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {NULL};
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject PK11SlotType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PK11Slot", /* tp_name */
|
|
sizeof(PK11Slot), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PK11Slot_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
PK11Slot_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PK11Slot_methods, /* tp_methods */
|
|
PK11Slot_members, /* tp_members */
|
|
PK11Slot_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PK11Slot_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PK11Slot_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
PK11Slot_new_from_PK11SlotInfo(PK11SlotInfo *slot)
|
|
{
|
|
PK11Slot *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (PK11Slot *) PK11SlotType.tp_new(&PK11SlotType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->slot = slot;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* =========================== PK11SymKey Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
PK11SymKey_get_mechanism(PyPK11SymKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(PK11_GetMechanism(self->pk11_sym_key));
|
|
}
|
|
|
|
static PyObject *
|
|
PK11SymKey_get_key_data(PyPK11SymKey *self, void *closure)
|
|
{
|
|
SECItem *sec_item;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_ExtractKeyValue(self->pk11_sym_key) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((sec_item = PK11_GetKeyData(self->pk11_sym_key)) == NULL) {
|
|
return PyString_FromStringAndSize("", 0);
|
|
}
|
|
|
|
return PyString_FromStringAndSize((const char *)sec_item->data, sec_item->len);
|
|
}
|
|
|
|
static PyObject *
|
|
PK11SymKey_get_key_length(PyPK11SymKey *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(PK11_GetKeyLength(self->pk11_sym_key));
|
|
}
|
|
|
|
static PyObject *
|
|
PK11SymKey_get_slot(PyPK11SymKey *self, void *closure)
|
|
{
|
|
PK11SlotInfo *slot = NULL;
|
|
PyObject *py_slot = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
slot = PK11_GetSlotFromKey(self->pk11_sym_key);
|
|
if ((py_slot = PK11Slot_new_from_PK11SlotInfo(slot)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Slot object");
|
|
return NULL;
|
|
}
|
|
return py_slot;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef PK11SymKey_getseters[] = {
|
|
{"mechanism", (getter)PK11SymKey_get_mechanism, (setter)NULL, "CK_MECHANISM_TYPE mechanism", NULL},
|
|
{"key_data", (getter)PK11SymKey_get_key_data, (setter)NULL, "key data", NULL},
|
|
{"key_length", (getter)PK11SymKey_get_key_length, (setter)NULL, "key length", NULL},
|
|
{"slot", (getter)PK11SymKey_get_slot, (setter)NULL, "slot", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PK11SymKey_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(PK11SymKey_derive_doc,
|
|
"derive(mechanism, sec_param, target, operation, key_size) -> PK11SymKey\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
sec_param : SecItem object or None\n\
|
|
mechanism parameters or None.\n\
|
|
target : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
operation : int\n\
|
|
type of operation. A (CKA_*) constant\n\
|
|
(e.g. CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, CKA_VERIFY, CKA_DIGEST)\n\
|
|
key_size : int\n\
|
|
key size.\n\
|
|
\n\
|
|
Derive a new key from this key.\n\
|
|
Return a key which can do exactly one operation, it is\n\
|
|
ephemeral (session key).\n\
|
|
");
|
|
static PyObject *
|
|
PK11SymKey_derive(PyPK11SymKey *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
SecItem *py_sec_param;
|
|
unsigned long target;
|
|
unsigned long operation;
|
|
int key_size;
|
|
PK11SymKey *derived_key = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "kO&kki:derive",
|
|
&mechanism, SecItemOrNoneConvert, &py_sec_param,
|
|
&target, &operation, &key_size))
|
|
return NULL;
|
|
|
|
if ((derived_key = PK11_Derive(self->pk11_sym_key, mechanism,
|
|
py_sec_param ? &py_sec_param->item : NULL,
|
|
target, operation, key_size)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return PyPK11SymKey_new_from_PK11SymKey(derived_key);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11SymKey_wrap_sym_key_doc,
|
|
"wrap_sym_key(mechanism, sec_param, sym_key) -> SecItem\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
sec_param : SecItem object or None\n\
|
|
mechanism parameters or None.\n\
|
|
sym_key : PK11SymKey object\n\
|
|
the symmetric key to wrap\n\
|
|
\n\
|
|
Wrap (encrypt) the supplied sym_key using the mechanism\n\
|
|
and parameter. Return the wrapped key as a SecItem.\n\
|
|
");
|
|
static PyObject *
|
|
PK11SymKey_wrap_sym_key(PyPK11SymKey *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
SecItem *py_sec_param;
|
|
PyPK11SymKey *py_sym_key = NULL;
|
|
SECItem wrapped_key;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "kO&O!:wrap_sym_key",
|
|
&mechanism, SecItemOrNoneConvert, &py_sec_param,
|
|
&PK11SymKeyType, &py_sym_key))
|
|
return NULL;
|
|
|
|
if (PK11_WrapSymKey(mechanism, py_sec_param ? &py_sec_param->item : NULL,
|
|
self->pk11_sym_key, py_sym_key->pk11_sym_key,
|
|
&wrapped_key) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return SecItem_new_from_SECItem(&wrapped_key, SECITEM_wrapped_key);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11SymKey_unwrap_sym_key_doc,
|
|
"unwrap_sym_key(mechanism, sec_param, wrapped_key, target, operation, key_size) -> PK11SymKey\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
sec_param : SecItem object or None\n\
|
|
mechanism parameters or None.\n\
|
|
wrapped_key : SecItem object\n\
|
|
the symmetric key to unwrap\n\
|
|
target : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
operation : int\n\
|
|
type of operation. A (CKA_*) constant\n\
|
|
(e.g. CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, CKA_VERIFY, CKA_DIGEST)\n\
|
|
key_size : int\n\
|
|
key size.\n\
|
|
\n\
|
|
Unwrap (decrypt) the supplied wrapped key.\n\
|
|
Return the unwrapped key as a PK11SymKey.\n\
|
|
");
|
|
static PyObject *
|
|
PK11SymKey_unwrap_sym_key(PyPK11SymKey *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
SecItem *py_sec_param;
|
|
unsigned long target;
|
|
unsigned long operation;
|
|
int key_size;
|
|
SecItem *py_wrapped_key = NULL;
|
|
PK11SymKey *sym_key = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "kO&O!kki:unwrap_sym_key",
|
|
&mechanism, SecItemOrNoneConvert, &py_sec_param,
|
|
&SecItemType, &py_wrapped_key,
|
|
&target, &operation, &key_size))
|
|
return NULL;
|
|
|
|
if ((sym_key = PK11_UnwrapSymKey(self->pk11_sym_key, mechanism,
|
|
py_sec_param ? &py_sec_param->item : NULL,
|
|
&py_wrapped_key->item,
|
|
target, operation, key_size)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return PyPK11SymKey_new_from_PK11SymKey(sym_key);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
PK11SymKey_repr(PyPK11SymKey *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyObject *
|
|
PK11SymKey_str(PyPK11SymKey *self)
|
|
{
|
|
return PK11SymKey_repr(self);
|
|
}
|
|
|
|
static PyMethodDef PK11SymKey_methods[] = {
|
|
{"derive", (PyCFunction)PK11SymKey_derive, METH_VARARGS, PK11SymKey_derive_doc},
|
|
{"wrap_sym_key", (PyCFunction)PK11SymKey_wrap_sym_key, METH_VARARGS, PK11SymKey_wrap_sym_key_doc},
|
|
{"unwrap_sym_key", (PyCFunction)PK11SymKey_unwrap_sym_key, METH_VARARGS, PK11SymKey_unwrap_sym_key_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static void
|
|
PK11SymKey_dealloc(PyPK11SymKey* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->pk11_sym_key) {
|
|
PK11_FreeSymKey(self->pk11_sym_key);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11SymKey_doc,
|
|
"Holds a hash, encryption or signing context for multi-part operations.\n\
|
|
");
|
|
static int
|
|
PK11SymKey_init(PyPK11SymKey *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject PK11SymKeyType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PK11SymKey", /* tp_name */
|
|
sizeof(PyPK11SymKey), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PK11SymKey_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)PK11SymKey_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)PK11SymKey_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
PK11SymKey_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PK11SymKey_methods, /* tp_methods */
|
|
PK11SymKey_members, /* tp_members */
|
|
PK11SymKey_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PK11SymKey_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
0,/* NULL cannot be directly created */ /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
PyPK11SymKey_new_from_PK11SymKey(PK11SymKey *pk11_sym_key)
|
|
{
|
|
PyPK11SymKey *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = PyObject_NEW(PyPK11SymKey, &PK11SymKeyType)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->pk11_sym_key = pk11_sym_key;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================ PK11Context Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef PK11Context_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PK11Context_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(PK11Context_digest_key_doc,
|
|
"digest_key(sym_key)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
sym_key : PK11SymKey object\n\
|
|
symmetric key\n\
|
|
\n\
|
|
Continues a multiple-part message-digesting operation by digesting the\n\
|
|
value of a secret key.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_digest_key(PyPK11Context *self, PyObject *args)
|
|
{
|
|
PyPK11SymKey *py_sym_key;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O!:digest_key", &PK11SymKeyType, &py_sym_key))
|
|
return NULL;
|
|
|
|
if (PK11_DigestKey(self->pk11_context, py_sym_key->pk11_sym_key) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_clone_context_doc,
|
|
"clone_context(context) -> PK11Context\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
context : PK11Context object\n\
|
|
The PK11Context to be cloned\n\
|
|
\n\
|
|
Create a new PK11Context which is clone of the supplied context.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_clone_context(PyPK11Context *self, PyObject *args)
|
|
{
|
|
PK11Context *pk11_context;
|
|
PyObject *py_pk11_context;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O!:clone_context", &PK11ContextType, &py_pk11_context))
|
|
return NULL;
|
|
|
|
if ((pk11_context = PK11_CloneContext(self->pk11_context)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((py_pk11_context =
|
|
PyPK11Context_new_from_PK11Context(pk11_context)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Context object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_pk11_context;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_digest_begin_doc,
|
|
"digest_begin()\n\
|
|
\n\
|
|
Start a new digesting or Mac'ing operation on this context.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_digest_begin(PyPK11Context *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_DigestBegin(self->pk11_context) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_digest_op_doc,
|
|
"digest_op(data)\n\
|
|
:Parameters:\n\
|
|
data : any read buffer compatible object (e.g. buffer or string)\n\
|
|
raw data to compute digest from\n\
|
|
\n\
|
|
Execute a digest/signature operation.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_digest_op(PyPK11Context *self, PyObject *args)
|
|
{
|
|
const void *buffer = NULL;
|
|
Py_ssize_t buffer_len;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "t#:digest_op", &buffer, &buffer_len))
|
|
return NULL;
|
|
|
|
if (PK11_DigestOp(self->pk11_context, buffer, buffer_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_cipher_op_doc,
|
|
"cipher_op(data) -> data\n\
|
|
:Parameters:\n\
|
|
data : any read buffer compatible object (e.g. buffer or string)\n\
|
|
raw data to compute digest from\n\
|
|
\n\
|
|
Execute a digest/signature operation.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_cipher_op(PyPK11Context *self, PyObject *args)
|
|
{
|
|
const void *in_buf = NULL;
|
|
void *out_buf = NULL;
|
|
PyObject *py_out_string;
|
|
Py_ssize_t in_buf_len;
|
|
Py_ssize_t out_buf_alloc_len;
|
|
int suggested_out_len = 0, actual_out_len;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "t#:cipher_op", &in_buf, &in_buf_len))
|
|
return NULL;
|
|
|
|
/*
|
|
* Create an output buffer to hold the result.
|
|
*/
|
|
|
|
/*
|
|
* We call the PK11 function with a NULL output buffer and it returns an
|
|
* upper bound on the size of the output data buffer. We create a string to
|
|
* hold the data using the upper bound as it's size. We then invoke the PK11
|
|
* function again which performs the operation writing into string buffer.
|
|
* It returns the exact number of bytes written. If the allocated size does
|
|
* not equal the actual number of bytes written we resize the string before
|
|
* returning it so the caller sees a string whose length exactly matches
|
|
* the number of bytes written by the PK11 function.
|
|
*/
|
|
if (PK11_CipherOp(self->pk11_context, NULL, &suggested_out_len, 0,
|
|
(unsigned char *)in_buf, in_buf_len) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
out_buf_alloc_len = suggested_out_len;
|
|
|
|
if ((py_out_string = PyString_FromStringAndSize(NULL, out_buf_alloc_len)) == NULL) {
|
|
return NULL;
|
|
}
|
|
out_buf = PyString_AsString(py_out_string);
|
|
|
|
/*
|
|
* Now that we have both the input and output buffers perform the cipher operation.
|
|
*/
|
|
if (PK11_CipherOp(self->pk11_context, out_buf, &actual_out_len, out_buf_alloc_len,
|
|
(unsigned char *)in_buf, in_buf_len) != SECSuccess) {
|
|
Py_DECREF(py_out_string);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if (actual_out_len != out_buf_alloc_len) {
|
|
if (_PyString_Resize(&py_out_string, actual_out_len) < 0) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return py_out_string;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_finalize_doc,
|
|
"finalize()\n\
|
|
\n\
|
|
Clean up cipher operation so that any pending multi-part\n\
|
|
operations have been flushed. Any pending output which would\n\
|
|
have been available as a result of the flush is discarded.\n\
|
|
The context is left in a state available for reuse.\n\
|
|
\n\
|
|
WARNING: Currently context reuse only works for digest contexts\n\
|
|
not encryption/decryption contexts\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_finalize(PyPK11Context *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_Finalize(self->pk11_context) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_digest_final_doc,
|
|
"digest_final() -> data\n\
|
|
\n\
|
|
Completes the multi-part cryptographic operation in progress\n\
|
|
on this context and returns any final data which may have been\n\
|
|
pending in the context (i.e. the output data is flushed from the\n\
|
|
context). If there was no final data the returned\n\
|
|
data buffer will have a length of zero.\n\
|
|
");
|
|
static PyObject *
|
|
PK11Context_digest_final(PyPK11Context *self, PyObject *args)
|
|
{
|
|
void *out_buf = NULL;
|
|
Py_ssize_t out_buf_alloc_len;
|
|
unsigned int suggested_out_len = 0, actual_out_len;
|
|
PyObject *py_out_string;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
/*
|
|
* We call the PK11 function with a NULL output buffer and it returns an
|
|
* upper bound on the size of the output data buffer. We create a string to
|
|
* hold the data using the upper bound as it's size. We then invoke the PK11
|
|
* function again which performs the operation writing into string buffer.
|
|
* It returns the exact number of bytes written. If the allocated size does
|
|
* not equal the actual number of bytes written we resize the string before
|
|
* returning it so the caller sees a string whose length exactly matches
|
|
* the number of bytes written by the PK11 function.
|
|
*/
|
|
|
|
if (PK11_DigestFinal(self->pk11_context, NULL, &suggested_out_len, 0) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
out_buf_alloc_len = suggested_out_len;
|
|
|
|
if ((py_out_string = PyString_FromStringAndSize(NULL, out_buf_alloc_len)) == NULL) {
|
|
return NULL;
|
|
}
|
|
out_buf = PyString_AsString(py_out_string);
|
|
|
|
/*
|
|
* Now that we have the output buffer perform the cipher operation.
|
|
*/
|
|
if (PK11_DigestFinal(self->pk11_context, out_buf,
|
|
&actual_out_len, out_buf_alloc_len) != SECSuccess) {
|
|
Py_DECREF(py_out_string);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if (actual_out_len != out_buf_alloc_len) {
|
|
if (_PyString_Resize(&py_out_string, actual_out_len) < 0) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return py_out_string;
|
|
}
|
|
|
|
static PyObject *
|
|
PK11Context_repr(PyPK11Context *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyObject *
|
|
PK11Context_str(PyPK11Context *self)
|
|
{
|
|
return PK11Context_repr(self);
|
|
}
|
|
|
|
static PyMethodDef PK11Context_methods[] = {
|
|
{"digest_key", (PyCFunction)PK11Context_digest_key, METH_VARARGS, PK11Context_digest_key_doc},
|
|
{"clone_context", (PyCFunction)PK11Context_clone_context, METH_VARARGS, PK11Context_clone_context_doc},
|
|
{"digest_begin", (PyCFunction)PK11Context_digest_begin, METH_NOARGS, PK11Context_digest_begin_doc},
|
|
{"digest_op", (PyCFunction)PK11Context_digest_op, METH_VARARGS, PK11Context_digest_op_doc},
|
|
{"cipher_op", (PyCFunction)PK11Context_cipher_op, METH_VARARGS, PK11Context_cipher_op_doc},
|
|
{"finalize", (PyCFunction)PK11Context_finalize, METH_NOARGS, PK11Context_finalize_doc},
|
|
{"digest_final", (PyCFunction)PK11Context_digest_final, METH_NOARGS, PK11Context_digest_final_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
PK11Context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
PyPK11Context *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (PyPK11Context *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->pk11_context = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
PK11Context_dealloc(PyPK11Context* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->pk11_context) {
|
|
PK11_DestroyContext(self->pk11_context, PR_TRUE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PK11Context_doc,
|
|
"\n\
|
|
");
|
|
static int
|
|
PK11Context_init(PyPK11Context *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyTypeObject PK11ContextType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PK11Context", /* tp_name */
|
|
sizeof(PyPK11Context), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PK11Context_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)PK11Context_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)PK11Context_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
PK11Context_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PK11Context_methods, /* tp_methods */
|
|
PK11Context_members, /* tp_members */
|
|
PK11Context_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PK11Context_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PK11Context_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
PyPK11Context_new_from_PK11Context(PK11Context *pk11_context)
|
|
|
|
{
|
|
PyPK11Context *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (PyPK11Context *) PK11ContextType.tp_new(&PK11ContextType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->pk11_context = pk11_context;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ======================== CRLDistributionPt Class ========================= */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_get_crl_issuer(CRLDistributionPt *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!self->pt || !self->pt->crlIssuer) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
return GeneralName_new_from_CERTGeneralName(self->pt->crlIssuer);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef CRLDistributionPt_getseters[] = {
|
|
{"issuer", (getter)CRLDistributionPt_get_crl_issuer, (setter)NULL,
|
|
"returns the CRL Issuer as a `GeneralName` object if defined, returns None if not defined", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CRLDistributionPt_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(CRLDistributionPt_get_general_names_doc,
|
|
"get_general_names(repr_kind=AsString) -> (general_name, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsObject\n\
|
|
The general name as a nss.GeneralName object\n\
|
|
AsString\n\
|
|
The general name as a string.\n\
|
|
(e.g. \"http://crl.geotrust.com/crls/secureca.crl\")\n\
|
|
AsTypeString\n\
|
|
The general name type as a string.\n\
|
|
(e.g. \"URI\")\n\
|
|
AsTypeEnum\n\
|
|
The general name type as a general name type enumerated constant.\n\
|
|
(e.g. nss.certURI )\n\
|
|
AsLabeledString\n\
|
|
The general name as a string with it's type prepended.\n\
|
|
(e.g. \"URI: http://crl.geotrust.com/crls/secureca.crl\"\n\
|
|
\n\
|
|
Returns a tuple of general names in the CRL Distribution Point. If the\n\
|
|
distribution point type is not nss.generalName or the list was empty then\n\
|
|
the returned tuple will be empty.\n\
|
|
\n\
|
|
You may specify how the each member of the tuple is represented, by default\n\
|
|
it will be as a string.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_get_general_names(CRLDistributionPt *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"repr_kind", NULL};
|
|
int repr_kind = AsString;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:get_general_names", kwlist,
|
|
&repr_kind))
|
|
return NULL;
|
|
|
|
return CRLDistributionPt_general_names_tuple(self, repr_kind);
|
|
}
|
|
|
|
PyDoc_STRVAR(CRLDistributionPt_get_reasons_doc,
|
|
"get_reasons(repr_kind=AsEnumDescription) -> (reason, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant.\n\
|
|
(e.g. nss.crlEntryReasonCaCompromise)\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
(e.g. \"CA Compromise\")\n\
|
|
AsIndex\n\
|
|
The bit position within the bit string.\n\
|
|
\n\
|
|
Returns a tuple of reasons in the CRL Distribution Point. If no\n\
|
|
reasons were defined the returned tuple will be empty.\n\
|
|
\n\
|
|
You may specify how the each member of the tuple is represented, by default\n\
|
|
it will be as a string.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_get_reasons(CRLDistributionPt *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"repr_kind", NULL};
|
|
int repr_kind = AsEnumDescription;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:get_reasons", kwlist,
|
|
&repr_kind))
|
|
return NULL;
|
|
|
|
return crl_reason_bitstr_to_tuple(&self->pt->bitsmap, repr_kind);
|
|
}
|
|
|
|
PyObject *
|
|
CRLDistributionPt_format_lines(CRLDistributionPt *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
Py_ssize_t len;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!self->pt) {
|
|
return lines;
|
|
}
|
|
|
|
if (self->pt->distPointType == generalName) {
|
|
if ((obj = CRLDistributionPt_general_names_tuple(self, AsString)) == NULL) {
|
|
goto fail;
|
|
}
|
|
len = PyTuple_GET_SIZE(obj);
|
|
|
|
if ((obj1 = PyString_FromFormat("General Names: [%d total]", len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj1, level, fail);
|
|
Py_CLEAR(obj1);
|
|
|
|
APPEND_LINES_AND_CLEAR(lines, obj, level+1, fail);
|
|
|
|
} else if (self->pt->distPointType == relativeDistinguishedName) {
|
|
|
|
if ((obj = RDN_new_from_CERTRDN(&self->pt->distPoint.relativeName)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Relative Distinguished Name"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
} else {
|
|
PyErr_Format(PyExc_ValueError, "unknown distribution point type (%d), "
|
|
"expected generalName or relativeDistinguishedName",
|
|
self->pt->distPointType);
|
|
goto fail;
|
|
}
|
|
|
|
if ((obj = CRLDistributionPt_get_crl_issuer(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Issuer"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = crl_reason_bitstr_to_tuple(&self->pt->bitsmap, AsEnumDescription)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Reasons"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(lines);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_format(CRLDistributionPt *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)CRLDistributionPt_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_str(CRLDistributionPt *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = CRLDistributionPt_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_repr(CRLDistributionPt *self)
|
|
{
|
|
PyObject *result = NULL;
|
|
PyObject *rdn = NULL;
|
|
PyObject *names = NULL;
|
|
PyObject *name_str = NULL;
|
|
PyObject *name_desc = NULL;
|
|
PyObject *crl_issuer = NULL;
|
|
PyObject *crl_issuer_str = NULL;
|
|
PyObject *reasons = NULL;
|
|
PyObject *reasons_str = NULL;
|
|
PyObject *sep = NULL;
|
|
|
|
if (!self->pt) {
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
if ((sep = PyString_FromString(", ")) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if (self->pt->distPointType == generalName) {
|
|
if ((names = CRLDistributionPt_general_names_tuple(self, AsString)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
/* Paste them all together with ", " between. */
|
|
if ((name_str = _PyString_Join(sep, names)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
name_desc = PyString_FromFormat(_("General Name List: [%s]"),
|
|
PyString_AsString(name_str));
|
|
|
|
} else if (self->pt->distPointType == relativeDistinguishedName) {
|
|
|
|
if ((rdn = RDN_new_from_CERTRDN(&self->pt->distPoint.relativeName)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((name_str = PyObject_Str(rdn)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
name_desc = PyString_FromFormat(_("Relative Distinguished Name: %s"),
|
|
PyString_AsString(name_str));
|
|
|
|
} else {
|
|
PyErr_Format(PyExc_ValueError, "unknown distribution point type (%d), "
|
|
"expected generalName or relativeDistinguishedName",
|
|
self->pt->distPointType);
|
|
goto exit;
|
|
}
|
|
|
|
if ((crl_issuer = CRLDistributionPt_get_crl_issuer(self, NULL)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((crl_issuer_str = PyObject_Str(crl_issuer)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((reasons = crl_reason_bitstr_to_tuple(&self->pt->bitsmap, AsEnumDescription)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((reasons_str = _PyString_Join(sep, reasons)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
result = PyString_FromFormat("%s, Issuer: %s, Reasons: [%s]",
|
|
PyString_AsString(name_desc),
|
|
PyString_AsString(crl_issuer_str),
|
|
PyString_AsString(reasons_str));
|
|
|
|
exit:
|
|
Py_XDECREF(rdn);
|
|
Py_XDECREF(names);
|
|
Py_XDECREF(name_str);
|
|
Py_XDECREF(name_desc);
|
|
Py_XDECREF(crl_issuer);
|
|
Py_XDECREF(crl_issuer_str);
|
|
Py_XDECREF(reasons);
|
|
Py_XDECREF(reasons_str);
|
|
Py_XDECREF(sep);
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyMethodDef CRLDistributionPt_methods[] = {
|
|
{"format_lines", (PyCFunction)CRLDistributionPt_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)CRLDistributionPt_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{"get_general_names", (PyCFunction)CRLDistributionPt_get_general_names, METH_VARARGS|METH_KEYWORDS, CRLDistributionPt_get_general_names_doc},
|
|
{"get_reasons", (PyCFunction)CRLDistributionPt_get_reasons, METH_VARARGS|METH_KEYWORDS, CRLDistributionPt_get_reasons_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CRLDistributionPt *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CRLDistributionPt *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->pt = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
CRLDistributionPt_dealloc(CRLDistributionPt* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CRLDistributionPt_doc,
|
|
"An object representing a CRL Distribution Point");
|
|
|
|
static int
|
|
CRLDistributionPt_init(CRLDistributionPt *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"arg1", NULL};
|
|
PyObject *arg;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:CRLDistributionPt", kwlist,
|
|
&arg))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
CRLDistributionPt_general_names_count(CRLDistributionPt *self)
|
|
{
|
|
if (!self->pt || self->pt->distPointType != generalName) {
|
|
return 0;
|
|
}
|
|
|
|
return CERTGeneralName_list_count(self->pt->distPoint.fullName);
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPt_general_names_tuple(CRLDistributionPt *self, RepresentationKind repr_kind)
|
|
{
|
|
Py_ssize_t n_names;
|
|
|
|
n_names = CRLDistributionPt_general_names_count(self);
|
|
|
|
if (n_names == 0) {
|
|
Py_INCREF(empty_tuple);
|
|
return empty_tuple;
|
|
}
|
|
|
|
return CERTGeneralName_list_to_tuple(self->pt->distPoint.fullName, repr_kind);
|
|
}
|
|
|
|
|
|
static PyTypeObject CRLDistributionPtType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CRLDistributionPoint", /* tp_name */
|
|
sizeof(CRLDistributionPt), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CRLDistributionPt_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)CRLDistributionPt_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)CRLDistributionPt_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
CRLDistributionPt_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CRLDistributionPt_methods, /* tp_methods */
|
|
CRLDistributionPt_members, /* tp_members */
|
|
CRLDistributionPt_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)CRLDistributionPt_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CRLDistributionPt_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
CRLDistributionPt_new_from_CRLDistributionPoint(CRLDistributionPoint *pt)
|
|
{
|
|
CRLDistributionPt *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (CRLDistributionPt *) CRLDistributionPtType.tp_new(&CRLDistributionPtType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (CERT_CopyCRLDistributionPoint(self->arena, &self->pt, pt) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ======================== CRLDistributionPts Class ======================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef CRLDistributionPts_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CRLDistributionPts_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
/* =========================== Sequence Protocol ============================ */
|
|
|
|
static Py_ssize_t
|
|
CERTCrlDistributionPoints_count(CERTCrlDistributionPoints *dist_pts)
|
|
{
|
|
Py_ssize_t count;
|
|
CRLDistributionPoint **pts;
|
|
|
|
if (!dist_pts) return 0;
|
|
for (pts = dist_pts->distPoints, count = 0; *pts; pts++, count++);
|
|
|
|
return count;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
CRLDistributionPts_length(CRLDistributionPts *self)
|
|
{
|
|
if (!self->py_pts) return 0;
|
|
return PyTuple_Size(self->py_pts);
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPts_item(CRLDistributionPts *self, register Py_ssize_t i)
|
|
{
|
|
PyObject *py_pt = NULL;
|
|
|
|
if (!self->py_pts) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
py_pt = PyTuple_GetItem(self->py_pts, i);
|
|
Py_XINCREF(py_pt);
|
|
return py_pt;
|
|
}
|
|
|
|
static PyMethodDef CRLDistributionPts_methods[] = {
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static int
|
|
CRLDistributionPts_init_from_SECItem(CRLDistributionPts *self, SECItem *item)
|
|
{
|
|
CERTCrlDistributionPoints *dist_pts;
|
|
CRLDistributionPoint **pts, *pt;
|
|
PLArenaPool *arena;
|
|
Py_ssize_t count, i;
|
|
PyObject *py_pts = NULL;
|
|
|
|
Py_CLEAR(self->py_pts);
|
|
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if ((dist_pts = CERT_DecodeCRLDistributionPoints(arena, item)) == NULL) {
|
|
PyErr_SetString(PyExc_ValueError, "Failed to parse CRL Distribution Point Extension");
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return -1;
|
|
}
|
|
|
|
count = CERTCrlDistributionPoints_count(dist_pts);
|
|
|
|
if ((py_pts = PyTuple_New(count)) == NULL) {
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return -1;
|
|
}
|
|
|
|
for (pts = dist_pts->distPoints, i = 0; (pt = *pts); pts++, i++) {
|
|
PyObject *py_crl_dist_pt;
|
|
|
|
if ((py_crl_dist_pt = CRLDistributionPt_new_from_CRLDistributionPoint(pt)) == NULL) {
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
Py_CLEAR(py_pts);
|
|
return -1;
|
|
}
|
|
|
|
PyTuple_SetItem(py_pts, i, py_crl_dist_pt);
|
|
}
|
|
|
|
ASSIGN_NEW_REF(self->py_pts, py_pts);
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPts_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CRLDistributionPts *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CRLDistributionPts *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->py_pts = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
CRLDistributionPts_traverse(CRLDistributionPts *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_pts);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
CRLDistributionPts_clear(CRLDistributionPts* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_pts);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
CRLDistributionPts_dealloc(CRLDistributionPts* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
CRLDistributionPts_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CRLDistributionPts_doc,
|
|
"An object representing CRL Distribution Points list");
|
|
|
|
static int
|
|
CRLDistributionPts_init(CRLDistributionPts *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"crl_dist_pt_extension", NULL};
|
|
SecItem *py_sec_item;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:CRLDistributionPts", kwlist,
|
|
&SecItemType, &py_sec_item))
|
|
return -1;
|
|
|
|
return CRLDistributionPts_init_from_SECItem(self, &py_sec_item->item);
|
|
}
|
|
|
|
static PyObject *
|
|
CRLDistributionPts_repr(CRLDistributionPts *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PySequenceMethods CRLDistributionPts_as_sequence = {
|
|
(lenfunc)CRLDistributionPts_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)CRLDistributionPts_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyTypeObject CRLDistributionPtsType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CRLDistributionPts", /* tp_name */
|
|
sizeof(CRLDistributionPts), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CRLDistributionPts_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)CRLDistributionPts_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&CRLDistributionPts_as_sequence, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
CRLDistributionPts_doc, /* tp_doc */
|
|
(traverseproc)CRLDistributionPts_traverse, /* tp_traverse */
|
|
(inquiry)CRLDistributionPts_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CRLDistributionPts_methods, /* tp_methods */
|
|
CRLDistributionPts_members, /* tp_members */
|
|
CRLDistributionPts_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)CRLDistributionPts_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CRLDistributionPts_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
CRLDistributionPts_new_from_SECItem(SECItem *item)
|
|
{
|
|
CRLDistributionPts *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (CRLDistributionPts *) CRLDistributionPtsType.tp_new(&CRLDistributionPtsType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (CRLDistributionPts_init_from_SECItem(self, item) < 0) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ============================ AuthKeyID Class ============================= */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
AuthKeyID_get_key_id(AuthKeyID *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!self->auth_key_id) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
if (!self->auth_key_id->keyID.len || !self->auth_key_id->keyID.data) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return SecItem_new_from_SECItem(&self->auth_key_id->keyID, SECITEM_unknown);
|
|
}
|
|
|
|
static PyObject *
|
|
AuthKeyID_get_serial_number(AuthKeyID *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (!self->auth_key_id) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
if (!self->auth_key_id->authCertSerialNumber.len || !self->auth_key_id->authCertSerialNumber.data) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return integer_secitem_to_pylong(&self->auth_key_id->authCertSerialNumber);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef AuthKeyID_getseters[] = {
|
|
{"key_id", (getter)AuthKeyID_get_key_id, (setter)NULL,
|
|
"Returns the key id as a SecItem", NULL},
|
|
{"serial_number", (getter)AuthKeyID_get_serial_number, (setter)NULL,
|
|
"Returns the key id as a SecItem", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef AuthKeyID_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(AuthKeyID_get_general_names_doc,
|
|
"get_general_names(repr_kind=AsString) -> (general_name, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsObject\n\
|
|
The general name as a nss.GeneralName object\n\
|
|
AsString\n\
|
|
The general name as a string.\n\
|
|
(e.g. \"http://crl.geotrust.com/crls/secureca.crl\")\n\
|
|
AsTypeString\n\
|
|
The general name type as a string.\n\
|
|
(e.g. \"URI\")\n\
|
|
AsTypeEnum\n\
|
|
The general name type as a general name type enumerated constant.\n\
|
|
(e.g. nss.certURI )\n\
|
|
AsLabeledString\n\
|
|
The general name as a string with it's type prepended.\n\
|
|
(e.g. \"URI: http://crl.geotrust.com/crls/secureca.crl\"\n\
|
|
\n\
|
|
Returns a tuple of general names in the authentication key id extension\n\
|
|
for the issuer. If the issuer was not defined then the returned tuple\n\
|
|
will be empty.\n\
|
|
\n\
|
|
You may specify how the each member of the tuple is represented, by default\n\
|
|
it will be as a string.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
AuthKeyID_get_general_names(AuthKeyID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"repr_kind", NULL};
|
|
int repr_kind = AsString;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:get_general_names", kwlist,
|
|
&repr_kind))
|
|
return NULL;
|
|
|
|
if (!self->auth_key_id) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
|
|
return AuthKeyID_general_names_tuple(self, repr_kind);
|
|
}
|
|
|
|
static PyObject *
|
|
AuthKeyID_format_lines(AuthKeyID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
Py_ssize_t len;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!self->auth_key_id) {
|
|
return lines;
|
|
}
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Key ID"), level, fail);
|
|
|
|
if ((obj = AuthKeyID_get_key_id(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
APPEND_OBJ_TO_HEX_LINES_AND_CLEAR(lines, obj, level+1, fail);
|
|
|
|
if ((obj = AuthKeyID_get_serial_number(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((obj1 = PyObject_Str(obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Serial Number"), obj1, level, fail);
|
|
Py_CLEAR(obj1);
|
|
|
|
if ((obj = AuthKeyID_general_names_tuple(self, AsString)) == NULL) {
|
|
goto fail;
|
|
}
|
|
len = PyObject_Size(obj);
|
|
if ((obj1 = PyString_FromFormat("General Names: [%d total]", len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj1, level, fail);
|
|
Py_CLEAR(obj1);
|
|
|
|
APPEND_LINES_AND_CLEAR(lines, obj, level+1, fail);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
AuthKeyID_format(AuthKeyID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)AuthKeyID_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
AuthKeyID_str(AuthKeyID *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = AuthKeyID_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
|
|
static PyMethodDef AuthKeyID_methods[] = {
|
|
{"format_lines", (PyCFunction)AuthKeyID_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)AuthKeyID_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{"get_general_names", (PyCFunction)AuthKeyID_get_general_names, METH_VARARGS|METH_KEYWORDS, AuthKeyID_get_general_names_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
AuthKeyID_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
AuthKeyID *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (AuthKeyID *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->auth_key_id = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
AuthKeyID_dealloc(AuthKeyID* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(AuthKeyID_doc,
|
|
"An object representing Authentication Key ID extension");
|
|
|
|
static int
|
|
AuthKeyID_init(AuthKeyID *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"auth_key_id", NULL};
|
|
SecItem *py_sec_item;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:AuthKeyID", kwlist,
|
|
&SecItemType, &py_sec_item))
|
|
return -1;
|
|
|
|
if ((self->auth_key_id = CERT_DecodeAuthKeyID(self->arena, &py_sec_item->item)) == NULL) {
|
|
set_nspr_error("cannot decode AuthKeyID");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
AuthKeyID_general_names_count(AuthKeyID *self)
|
|
{
|
|
if (!self->auth_key_id || !self->auth_key_id->authCertIssuer) {
|
|
return 0;
|
|
}
|
|
|
|
return CERTGeneralName_list_count(self->auth_key_id->authCertIssuer);
|
|
}
|
|
|
|
static PyObject *
|
|
AuthKeyID_general_names_tuple(AuthKeyID *self, RepresentationKind repr_kind)
|
|
{
|
|
Py_ssize_t n_names;
|
|
|
|
n_names = AuthKeyID_general_names_count(self);
|
|
|
|
if (n_names == 0) {
|
|
Py_INCREF(empty_tuple);
|
|
return empty_tuple;
|
|
}
|
|
|
|
return CERTGeneralName_list_to_tuple(self->auth_key_id->authCertIssuer, repr_kind);
|
|
}
|
|
|
|
static PyObject *
|
|
AuthKeyID_repr(AuthKeyID *self)
|
|
{
|
|
PyObject *result = NULL;
|
|
PyObject *sep = NULL;
|
|
PyObject *names = NULL;
|
|
PyObject *name_str = NULL;
|
|
PyObject *key_id = NULL;
|
|
PyObject *key_id_str = NULL;
|
|
PyObject *serial_number = NULL;
|
|
PyObject *serial_number_str = NULL;
|
|
|
|
if (!self->auth_key_id) {
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
if ((sep = PyString_FromString(", ")) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((names = AuthKeyID_general_names_tuple(self, AsString)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
/* Paste them all together with ", " between. */
|
|
if ((name_str = _PyString_Join(sep, names)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((key_id = AuthKeyID_get_key_id(self, NULL)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((key_id_str = PyObject_Str(key_id)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((serial_number = AuthKeyID_get_serial_number(self, NULL)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if ((serial_number_str = PyObject_Str(serial_number)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
result = PyString_FromFormat("ID: %s, Serial Number: %s, Issuer: [%s]",
|
|
PyString_AsString(key_id_str),
|
|
PyString_AsString(serial_number_str),
|
|
PyString_AsString(name_str));
|
|
|
|
|
|
exit:
|
|
Py_XDECREF(sep);
|
|
Py_XDECREF(names);
|
|
Py_XDECREF(name_str);
|
|
Py_XDECREF(key_id);
|
|
Py_XDECREF(key_id_str);
|
|
Py_XDECREF(serial_number);
|
|
Py_XDECREF(serial_number_str);
|
|
return result;
|
|
}
|
|
|
|
static PyTypeObject AuthKeyIDType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.AuthKeyID", /* tp_name */
|
|
sizeof(AuthKeyID), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)AuthKeyID_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)AuthKeyID_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)AuthKeyID_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
AuthKeyID_doc, /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
AuthKeyID_methods, /* tp_methods */
|
|
AuthKeyID_members, /* tp_members */
|
|
AuthKeyID_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)AuthKeyID_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
AuthKeyID_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
AuthKeyID_new_from_CERTAuthKeyID(CERTAuthKeyID *auth_key_id)
|
|
{
|
|
AuthKeyID *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (AuthKeyID *) AuthKeyIDType.tp_new(&AuthKeyIDType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (CERT_CopyAuthKeyID(self->arena, &self->auth_key_id, auth_key_id) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
PyObject *
|
|
AuthKeyID_new_from_SECItem(SECItem *item)
|
|
{
|
|
AuthKeyID *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (AuthKeyID *) AuthKeyIDType.tp_new(&AuthKeyIDType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->auth_key_id = CERT_DecodeAuthKeyID(self->arena, item)) == NULL) {
|
|
set_nspr_error("cannot decode AuthKeyID");
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
|
|
|
|
/* ========================================================================== */
|
|
/* ======================== BasicConstraints Class ========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
BasicConstraints_get_is_ca(BasicConstraints *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyBool_FromLong(self->bc.isCA);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
BasicConstraints_get_path_len(BasicConstraints *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->bc.pathLenConstraint);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef BasicConstraints_getseters[] = {
|
|
{"is_ca", (getter)BasicConstraints_get_is_ca, (setter)NULL,
|
|
"returns boolean, True if certificate is a certificate authority (i.e. CA)", NULL},
|
|
{"path_len", (getter)BasicConstraints_get_path_len, (setter)NULL,
|
|
"returns max path length constraint as an integer", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef BasicConstraints_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
BasicConstraints_format_lines(BasicConstraints *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
obj = self->bc.isCA ? Py_True : Py_False;
|
|
Py_INCREF(obj);
|
|
FMT_OBJ_AND_APPEND(lines, _("Is CA"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = PyString_FromFormat("%d", self->bc.pathLenConstraint)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Path Length"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
BasicConstraints_format(BasicConstraints *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)BasicConstraints_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyMethodDef BasicConstraints_methods[] = {
|
|
{"format_lines", (PyCFunction)BasicConstraints_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)BasicConstraints_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
BasicConstraints_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
BasicConstraints *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (BasicConstraints *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(&self->bc, 0, sizeof(self->bc));
|
|
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
BasicConstraints_dealloc(BasicConstraints* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(BasicConstraints_doc,
|
|
"An object representing X509 Basic Constraints Extension");
|
|
|
|
static int
|
|
BasicConstraints_init(BasicConstraints *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"basic_constraints", NULL};
|
|
SecItem *py_sec_item;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:BasicConstraints", kwlist,
|
|
&SecItemType, &py_sec_item))
|
|
|
|
return -1;
|
|
|
|
if (CERT_DecodeBasicConstraintValue(&self->bc, &py_sec_item->item) != SECSuccess) {
|
|
set_nspr_error("cannot decode Basic Constraints");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
BasicConstraints_repr(BasicConstraints *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyObject *
|
|
BasicConstraints_str(BasicConstraints *self)
|
|
{
|
|
return PyString_FromFormat("is_ca=%s path_len=%d",
|
|
self->bc.isCA ? "True" : "False", self->bc.pathLenConstraint);
|
|
}
|
|
|
|
static PyTypeObject BasicConstraintsType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.BasicConstraints", /* tp_name */
|
|
sizeof(BasicConstraints), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)BasicConstraints_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)BasicConstraints_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)BasicConstraints_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
BasicConstraints_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
BasicConstraints_methods, /* tp_methods */
|
|
BasicConstraints_members, /* tp_members */
|
|
BasicConstraints_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)BasicConstraints_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
BasicConstraints_new, /* tp_new */
|
|
};
|
|
|
|
PyObject *
|
|
BasicConstraints_new_from_SECItem(SECItem *item)
|
|
{
|
|
BasicConstraints *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (BasicConstraints *) BasicConstraintsType.tp_new(&BasicConstraintsType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (CERT_DecodeBasicConstraintValue(&self->bc, item) != SECSuccess) {
|
|
set_nspr_error("cannot decode Basic Constraints");
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ======================= CertificateRequest Class ========================= */
|
|
/* ========================================================================== */
|
|
|
|
static int
|
|
CertificateRequest_init_from_SECItem(CertificateRequest *self, SECItem *der_cert_req)
|
|
{
|
|
if ((self->cert_req = PORT_ArenaZAlloc(self->arena, sizeof(CERTCertificateRequest))) == NULL) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
self->cert_req->arena = self->arena;
|
|
|
|
/* Since cert request is a signed data, must decode to get the inner data */
|
|
if (SEC_ASN1DecodeItem(self->arena, &self->signed_data,
|
|
SEC_ASN1_GET(CERT_SignedDataTemplate),
|
|
der_cert_req) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
|
|
if (SEC_ASN1DecodeItem(self->arena, self->cert_req,
|
|
SEC_ASN1_GET(CERT_CertificateRequestTemplate),
|
|
&self->signed_data.data) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
|
|
if (CERT_VerifySignedDataWithPublicKeyInfo(&self->signed_data,
|
|
&self->cert_req->subjectPublicKeyInfo,
|
|
NULL) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
CertificateRequest_get_subject(CertificateRequest *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return DN_new_from_CERTName(&self->cert_req->subject);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateRequest_get_version(CertificateRequest *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return integer_secitem_to_pylong(&self->cert_req->version);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateRequest_get_subject_public_key_info(CertificateRequest *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return SubjectPublicKeyInfo_new_from_CERTSubjectPublicKeyInfo(
|
|
&self->cert_req->subjectPublicKeyInfo);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
CertificateRequest_get_extensions(CertificateRequest *self, void *closure)
|
|
{
|
|
CERTCertExtension **extensions_list = NULL, **extensions = NULL;
|
|
int num_extensions, i;
|
|
PyObject *extensions_tuple;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->cert_req->attributes != NULL &&
|
|
self->cert_req->attributes[0] != NULL &&
|
|
self->cert_req->attributes[0]->attrType.data != NULL &&
|
|
self->cert_req->attributes[0]->attrType.len > 0 &&
|
|
SECOID_FindOIDTag(&self->cert_req->attributes[0]->attrType) == SEC_OID_PKCS9_EXTENSION_REQUEST) {
|
|
if (CERT_GetCertificateRequestExtensions(self->cert_req, &extensions_list) != SECSuccess) {
|
|
return set_nspr_error("CERT_GetCertificateRequestExtensions failed");
|
|
}
|
|
} else {
|
|
Py_INCREF(empty_tuple);
|
|
return empty_tuple;
|
|
}
|
|
|
|
/* First count how many extensions the cert request has */
|
|
for (extensions = extensions_list, num_extensions = 0;
|
|
extensions && *extensions;
|
|
extensions++, num_extensions++);
|
|
|
|
/* Allocate a tuple */
|
|
if ((extensions_tuple = PyTuple_New(num_extensions)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Copy the extensions into the tuple */
|
|
for (extensions = extensions_list, i = 0; extensions && *extensions; extensions++, i++) {
|
|
CERTCertExtension *extension = *extensions;
|
|
PyObject *py_extension;
|
|
|
|
if ((py_extension = CertificateExtension_new_from_CERTCertExtension(extension)) == NULL) {
|
|
Py_DECREF(extensions_tuple);
|
|
return NULL;
|
|
}
|
|
|
|
PyTuple_SetItem(extensions_tuple, i, py_extension);
|
|
}
|
|
|
|
return extensions_tuple;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef CertificateRequest_getseters[] = {
|
|
{"subject", (getter)CertificateRequest_get_subject, (setter)NULL,
|
|
"subject as an `DN` object", NULL},
|
|
{"version", (getter)CertificateRequest_get_version, (setter)NULL,
|
|
"version as integer", NULL},
|
|
{"subject_public_key_info", (getter)CertificateRequest_get_subject_public_key_info, NULL,
|
|
"certificate public info as SubjectPublicKeyInfo object", NULL},
|
|
{"extensions", (getter)CertificateRequest_get_extensions, NULL,
|
|
"certificate extensions as a tuple of CertificateExtension objects", NULL},
|
|
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CertificateRequest_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
CertificateRequest_format_lines(CertificateRequest *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
Py_ssize_t len, i;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
PyObject *obj1 = NULL;
|
|
PyObject *obj2 = NULL;
|
|
PyObject *obj3 = NULL;
|
|
PyObject *extensions = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Data"), level+1, fail);
|
|
|
|
if ((obj = CertificateRequest_get_version(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj1 = PyInt_FromLong(1)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj2 = PyNumber_Add(obj, obj1)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj3 = obj_sprintf("%d (%#x)", obj2, obj)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Version"), obj3, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
Py_CLEAR(obj1);
|
|
Py_CLEAR(obj2);
|
|
Py_CLEAR(obj3);
|
|
|
|
if ((obj = CertificateRequest_get_subject(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Subject"), obj, level+2, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Subject Public Key Info"), level+2, fail);
|
|
|
|
if ((obj = CertificateRequest_get_subject_public_key_info(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+3, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((extensions = CertificateRequest_get_extensions(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
len = PyTuple_Size(extensions);
|
|
if ((obj = PyString_FromFormat("Signed Extensions: (%d)", len)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
obj = PyTuple_GetItem(extensions, i);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+2, fail);
|
|
FMT_LABEL_AND_APPEND(lines, NULL, 0, fail);
|
|
}
|
|
Py_CLEAR(extensions);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(obj1);
|
|
Py_XDECREF(obj2);
|
|
Py_XDECREF(obj3);
|
|
Py_XDECREF(lines);
|
|
Py_XDECREF(extensions);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateRequest_format(CertificateRequest *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)CertificateRequest_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateRequest_str(CertificateRequest *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
py_formatted_result = CertificateRequest_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
|
|
static PyMethodDef CertificateRequest_methods[] = {
|
|
{"format_lines", (PyCFunction)CertificateRequest_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)CertificateRequest_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
CertificateRequest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CertificateRequest *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CertificateRequest *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->cert_req = NULL;
|
|
memset(&self->signed_data, 0, sizeof(self->signed_data));
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
CertificateRequest_dealloc(CertificateRequest* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
/*
|
|
* We could call CERT_DestroyCertificateRequest() but all
|
|
* CERT_DestroyCertificateRequest() does is call PORT_FreeArena() on
|
|
* the arena stored in the CERTCertificateRequest. All the other
|
|
* dealloc routines for objects with arenas call PORT_FreeArena()
|
|
* explicitly, so for consistency and to make sure the freeing of
|
|
* the arena is explicit rather than hidden we do the same here.
|
|
*
|
|
* Also, self->signed_data does not need to be explicitly freed
|
|
* because it's allocated out of the arena.
|
|
*/
|
|
|
|
if (self->arena) {
|
|
PORT_FreeArena(self->arena, PR_FALSE);
|
|
}
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CertificateRequest_doc,
|
|
"CertificateRequest(data=None)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : SecItem or str or any buffer compatible object\n\
|
|
Data to initialize the certificate request from, must be in DER format\n\
|
|
\n\
|
|
An object representing a certificate request");
|
|
|
|
static int
|
|
CertificateRequest_init(CertificateRequest *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"data", NULL};
|
|
PyObject *py_data = NULL;
|
|
SECItem tmp_item;
|
|
SECItem *der_item = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:CertificateRequest", kwlist,
|
|
&py_data))
|
|
return -1;
|
|
|
|
if (py_data) {
|
|
if (PySecItem_Check(py_data)) {
|
|
der_item = &((SecItem *)py_data)->item;
|
|
} else if (PyObject_CheckReadBuffer(py_data)) {
|
|
unsigned char *data = NULL;
|
|
Py_ssize_t data_len;
|
|
|
|
if (PyObject_AsReadBuffer(py_data, (void *)&data, &data_len))
|
|
return -1;
|
|
|
|
tmp_item.data = data;
|
|
tmp_item.len = data_len;
|
|
der_item = &tmp_item;
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "data must be SecItem or buffer compatible");
|
|
return -1;
|
|
}
|
|
|
|
return CertificateRequest_init_from_SECItem(self, der_item);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
CertificateRequest_repr(CertificateRequest *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject CertificateRequestType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CertificateRequest", /* tp_name */
|
|
sizeof(CertificateRequest), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CertificateRequest_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)CertificateRequest_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)CertificateRequest_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
CertificateRequest_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CertificateRequest_methods, /* tp_methods */
|
|
CertificateRequest_members, /* tp_members */
|
|
CertificateRequest_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)CertificateRequest_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CertificateRequest_new, /* tp_new */
|
|
};
|
|
|
|
/* ========================================================================== */
|
|
/* ========================== InitParameters Class ========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
InitParameters_get_password_required(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyBool_FromLong(self->params.passwordRequired);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_password_required(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the password_required attribute");
|
|
return -1;
|
|
}
|
|
|
|
switch(PyObject_IsTrue(value)) {
|
|
case 0:
|
|
self->params.passwordRequired = PR_FALSE;
|
|
return 0;
|
|
case 1:
|
|
self->params.passwordRequired = PR_TRUE;
|
|
return 0;
|
|
default:
|
|
PyErr_SetString(PyExc_TypeError, "The password_required attribute value must be a boolean");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_min_password_len(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->params.minPWLen);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_min_password_len(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the min_password_len attribute");
|
|
return -1;
|
|
}
|
|
|
|
if (!PyInt_Check(value)) {
|
|
PyErr_SetString(PyExc_TypeError, "The min_password_len attribute value must be an integer");
|
|
return -1;
|
|
}
|
|
|
|
self->params.minPWLen = PyInt_AsLong(value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_manufacturer_id(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.manufactureID == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.manufactureID, strlen(self->params.manufactureID), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_manufacturer_id(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.manufactureID) {
|
|
PyMem_Free(self->params.manufactureID);
|
|
}
|
|
self->params.manufactureID = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The manufacturer_id attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.manufactureID) {
|
|
PyMem_Free(self->params.manufactureID);
|
|
self->params.manufactureID = NULL;
|
|
}
|
|
|
|
self->params.manufactureID = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_library_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.libraryDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.libraryDescription, strlen(self->params.libraryDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_library_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.libraryDescription) {
|
|
PyMem_Free(self->params.libraryDescription);
|
|
}
|
|
self->params.libraryDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The library_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.libraryDescription) {
|
|
PyMem_Free(self->params.libraryDescription);
|
|
self->params.libraryDescription = NULL;
|
|
}
|
|
|
|
self->params.libraryDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
InitParameters_get_crypto_token_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.cryptoTokenDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.cryptoTokenDescription, strlen(self->params.cryptoTokenDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_crypto_token_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.cryptoTokenDescription) {
|
|
PyMem_Free(self->params.cryptoTokenDescription);
|
|
}
|
|
self->params.cryptoTokenDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The crypto_token_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.cryptoTokenDescription) {
|
|
PyMem_Free(self->params.cryptoTokenDescription);
|
|
self->params.cryptoTokenDescription = NULL;
|
|
}
|
|
|
|
self->params.cryptoTokenDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
InitParameters_get_db_token_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.dbTokenDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.dbTokenDescription, strlen(self->params.dbTokenDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_db_token_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.dbTokenDescription) {
|
|
PyMem_Free(self->params.dbTokenDescription);
|
|
}
|
|
self->params.dbTokenDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The db_token_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.dbTokenDescription) {
|
|
PyMem_Free(self->params.dbTokenDescription);
|
|
self->params.dbTokenDescription = NULL;
|
|
}
|
|
|
|
self->params.dbTokenDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_fips_token_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.FIPSTokenDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.FIPSTokenDescription, strlen(self->params.FIPSTokenDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_fips_token_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.FIPSTokenDescription) {
|
|
PyMem_Free(self->params.FIPSTokenDescription);
|
|
}
|
|
self->params.FIPSTokenDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The fips_token_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.FIPSTokenDescription) {
|
|
PyMem_Free(self->params.FIPSTokenDescription);
|
|
self->params.FIPSTokenDescription = NULL;
|
|
}
|
|
|
|
self->params.FIPSTokenDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_crypto_slot_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.cryptoSlotDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.cryptoSlotDescription, strlen(self->params.cryptoSlotDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_crypto_slot_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.cryptoSlotDescription) {
|
|
PyMem_Free(self->params.cryptoSlotDescription);
|
|
}
|
|
self->params.cryptoSlotDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The crypto_slot_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.cryptoSlotDescription) {
|
|
PyMem_Free(self->params.cryptoSlotDescription);
|
|
self->params.cryptoSlotDescription = NULL;
|
|
}
|
|
|
|
self->params.cryptoSlotDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_db_slot_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.dbSlotDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.dbSlotDescription, strlen(self->params.dbSlotDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_db_slot_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.dbSlotDescription) {
|
|
PyMem_Free(self->params.dbSlotDescription);
|
|
}
|
|
self->params.dbSlotDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The db_slot_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.dbSlotDescription) {
|
|
PyMem_Free(self->params.dbSlotDescription);
|
|
self->params.dbSlotDescription = NULL;
|
|
}
|
|
|
|
self->params.dbSlotDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_get_fips_slot_description(InitParameters *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.FIPSSlotDescription == NULL) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
return PyUnicode_DecodeUTF8(self->params.FIPSSlotDescription, strlen(self->params.FIPSSlotDescription), NULL);
|
|
}
|
|
|
|
static int
|
|
InitParameters_set_fips_slot_description(InitParameters *self, PyObject *value, void *closure)
|
|
{
|
|
PyObject *args = NULL;
|
|
char *new_value = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (value == NULL) {
|
|
if (self->params.FIPSSlotDescription) {
|
|
PyMem_Free(self->params.FIPSSlotDescription);
|
|
}
|
|
self->params.FIPSSlotDescription = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if ((args = Py_BuildValue("(O)", value)) == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (PyArg_ParseTuple(args, "es", "utf-8", &new_value) == -1) {
|
|
Py_DECREF(args);
|
|
PyErr_SetString(PyExc_TypeError, "The fips_slot_description attribute value must be a string or unicode");
|
|
return -1;
|
|
}
|
|
|
|
if (self->params.FIPSSlotDescription) {
|
|
PyMem_Free(self->params.FIPSSlotDescription);
|
|
self->params.FIPSSlotDescription = NULL;
|
|
}
|
|
|
|
self->params.FIPSSlotDescription = new_value;
|
|
Py_DECREF(args);
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef InitParameters_getseters[] = {
|
|
{"password_required",
|
|
(getter)InitParameters_get_password_required,
|
|
(setter)InitParameters_set_password_required,
|
|
"boolean indicating if a password is required", NULL},
|
|
|
|
{"min_password_len",
|
|
(getter)InitParameters_get_min_password_len,
|
|
(setter)InitParameters_set_min_password_len,
|
|
"minimum password length", NULL},
|
|
|
|
{"manufacturer_id",
|
|
(getter)InitParameters_get_manufacturer_id,
|
|
(setter)InitParameters_set_manufacturer_id,
|
|
"manufacturer id (max 32 chars)", NULL},
|
|
|
|
{"library_description",
|
|
(getter)InitParameters_get_library_description,
|
|
(setter)InitParameters_set_library_description,
|
|
"", NULL},
|
|
|
|
{"crypto_token_description",
|
|
(getter)InitParameters_get_crypto_token_description,
|
|
(setter)InitParameters_set_crypto_token_description,
|
|
"", NULL},
|
|
|
|
{"db_token_description",
|
|
(getter)InitParameters_get_db_token_description,
|
|
(setter)InitParameters_set_db_token_description,
|
|
"", NULL},
|
|
|
|
{"fips_token_description",
|
|
(getter)InitParameters_get_fips_token_description,
|
|
(setter)InitParameters_set_fips_token_description,
|
|
"", NULL},
|
|
|
|
{"crypto_slot_description",
|
|
(getter)InitParameters_get_crypto_slot_description,
|
|
(setter)InitParameters_set_crypto_slot_description,
|
|
"", NULL},
|
|
|
|
{"db_slot_description",
|
|
(getter)InitParameters_get_db_slot_description,
|
|
(setter)InitParameters_set_db_slot_description,
|
|
"", NULL},
|
|
|
|
{"fips_slot_description",
|
|
(getter)InitParameters_get_fips_slot_description,
|
|
(setter)InitParameters_set_fips_slot_description,
|
|
"", NULL},
|
|
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyObject *
|
|
InitParameters_format_lines(InitParameters *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((obj = InitParameters_get_password_required(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Password Required"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_min_password_len(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Minimum Password Length"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_manufacturer_id(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Manufacturer ID"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_library_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Library Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_crypto_token_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Crypto Token Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_db_token_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Database Token Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_fips_token_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("FIPS Token Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_crypto_slot_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Crypto Slot Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_db_slot_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Database Slot Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((obj = InitParameters_get_fips_slot_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("FIPS Slot Description"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
return lines;
|
|
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_format(InitParameters *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)InitParameters_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyMemberDef InitParameters_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
|
|
static PyMethodDef InitParameters_methods[] = {
|
|
{"format_lines", (PyCFunction)InitParameters_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)InitParameters_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
InitParameters_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
InitParameters *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (InitParameters *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(&self->params, 0, sizeof(self->params));
|
|
self->params.length = sizeof(self->params);
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
InitParameters_dealloc(InitParameters* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->params.manufactureID) {
|
|
PyMem_Free(self->params.manufactureID);
|
|
}
|
|
if (self->params.libraryDescription) {
|
|
PyMem_Free(self->params.libraryDescription);
|
|
}
|
|
if (self->params.cryptoTokenDescription) {
|
|
PyMem_Free(self->params.cryptoTokenDescription);
|
|
}
|
|
if (self->params.dbTokenDescription) {
|
|
PyMem_Free(self->params.dbTokenDescription);
|
|
}
|
|
if (self->params.FIPSTokenDescription) {
|
|
PyMem_Free(self->params.FIPSTokenDescription);
|
|
}
|
|
if (self->params.cryptoSlotDescription) {
|
|
PyMem_Free(self->params.cryptoSlotDescription);
|
|
}
|
|
if (self->params.dbSlotDescription) {
|
|
PyMem_Free(self->params.dbSlotDescription);
|
|
}
|
|
if (self->params.FIPSSlotDescription) {
|
|
PyMem_Free(self->params.FIPSSlotDescription);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(InitParameters_doc,
|
|
"An object representing NSS Initialization Parameters");
|
|
|
|
static int
|
|
InitParameters_init(InitParameters *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"password_required",
|
|
"min_password_len",
|
|
"manufacturer_id",
|
|
"library_description",
|
|
"crypto_token_description",
|
|
"db_token_description",
|
|
"fips_token_description",
|
|
"crypto_slot_description",
|
|
"db_slot_description",
|
|
"fips_slot_description",
|
|
NULL};
|
|
|
|
PyObject *py_password_required = NULL;
|
|
PyObject *py_min_password_len = NULL;
|
|
PyObject *py_manufacturer_id = NULL;
|
|
PyObject *py_library_description = NULL;
|
|
PyObject *py_crypto_token_description = NULL;
|
|
PyObject *py_db_token_description = NULL;
|
|
PyObject *py_fips_token_description = NULL;
|
|
PyObject *py_crypto_slot_description = NULL;
|
|
PyObject *py_db_slot_description = NULL;
|
|
PyObject *py_fips_slot_description = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOOOOO:InitParameters", kwlist,
|
|
&py_password_required,
|
|
&py_min_password_len,
|
|
&py_manufacturer_id,
|
|
&py_library_description,
|
|
&py_crypto_token_description,
|
|
&py_db_token_description,
|
|
&py_fips_token_description,
|
|
&py_crypto_slot_description,
|
|
&py_db_slot_description,
|
|
&py_fips_slot_description))
|
|
return -1;
|
|
|
|
if (py_password_required) {
|
|
if (InitParameters_set_password_required(self, py_password_required, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_min_password_len) {
|
|
if (InitParameters_set_min_password_len(self, py_min_password_len, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_manufacturer_id) {
|
|
if (InitParameters_set_manufacturer_id(self, py_manufacturer_id, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_library_description) {
|
|
if (InitParameters_set_library_description(self, py_library_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_crypto_token_description) {
|
|
if (InitParameters_set_crypto_token_description(self, py_crypto_token_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_db_token_description) {
|
|
if (InitParameters_set_db_token_description(self, py_db_token_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_fips_token_description) {
|
|
if (InitParameters_set_fips_token_description(self, py_fips_token_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_crypto_slot_description) {
|
|
if (InitParameters_set_crypto_slot_description(self, py_crypto_slot_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_db_slot_description) {
|
|
if (InitParameters_set_db_slot_description(self, py_db_slot_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (py_fips_slot_description) {
|
|
if (InitParameters_set_fips_slot_description(self, py_fips_slot_description, NULL) == -1) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
InitParameters_str(InitParameters *self)
|
|
{
|
|
const char *fmt_str = "password_required=%s, min_password_len=%s, manufacturer_id=%s, library_description=%s, crypto_token_description=%s, db_token_description=%s, fips_token_description=%s, crypto_slot_description=%s, db_slot_description=%s, fips_slot_description=%s";
|
|
|
|
PyObject *result = NULL;
|
|
PyObject *fmt = NULL;
|
|
PyObject *args = NULL;
|
|
PyObject *py_password_required = NULL;
|
|
PyObject *py_min_password_len = NULL;
|
|
PyObject *py_manufacturer_id = NULL;
|
|
PyObject *py_library_description = NULL;
|
|
PyObject *py_crypto_token_description = NULL;
|
|
PyObject *py_db_token_description = NULL;
|
|
PyObject *py_fips_token_description = NULL;
|
|
PyObject *py_crypto_slot_description = NULL;
|
|
PyObject *py_db_slot_description = NULL;
|
|
PyObject *py_fips_slot_description = NULL;
|
|
|
|
if ((py_password_required = InitParameters_get_password_required(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_min_password_len = InitParameters_get_min_password_len(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_manufacturer_id = InitParameters_get_manufacturer_id(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_library_description = InitParameters_get_library_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_crypto_token_description = InitParameters_get_crypto_token_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_db_token_description = InitParameters_get_db_token_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_fips_token_description = InitParameters_get_fips_token_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_crypto_slot_description = InitParameters_get_crypto_slot_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_db_slot_description = InitParameters_get_db_slot_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((py_fips_slot_description = InitParameters_get_fips_slot_description(self, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
|
|
if ((fmt = PyString_FromString(fmt_str)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((args = PyTuple_New(10)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
/*
|
|
* We bump the ref count when inserting into the tuple to simpify clean
|
|
* up. We always DECREF the variable on exit and also DECREF the
|
|
* tuple. When the tuple is deallocated it will DECREF it's members,
|
|
* then subsequently we'll individually DECREF the variable, thus
|
|
* requiring the INCREF when it's inserted into the tuple.
|
|
*/
|
|
PyTuple_SetItem(args, 0, py_password_required); Py_INCREF(py_password_required);
|
|
PyTuple_SetItem(args, 1, py_min_password_len); Py_INCREF(py_min_password_len);
|
|
PyTuple_SetItem(args, 2, py_manufacturer_id); Py_INCREF(py_manufacturer_id);
|
|
PyTuple_SetItem(args, 3, py_library_description); Py_INCREF(py_library_description);
|
|
PyTuple_SetItem(args, 4, py_crypto_token_description); Py_INCREF(py_crypto_token_description);
|
|
PyTuple_SetItem(args, 5, py_db_token_description); Py_INCREF(py_db_token_description);
|
|
PyTuple_SetItem(args, 6, py_fips_token_description); Py_INCREF(py_fips_token_description);
|
|
PyTuple_SetItem(args, 7, py_crypto_slot_description); Py_INCREF(py_crypto_slot_description);
|
|
PyTuple_SetItem(args, 8, py_db_slot_description); Py_INCREF(py_db_slot_description);
|
|
PyTuple_SetItem(args, 9, py_fips_slot_description); Py_INCREF(py_fips_slot_description);
|
|
|
|
if ((result = PyString_Format(fmt, args)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
goto exit;
|
|
|
|
fail:
|
|
Py_CLEAR(result);
|
|
exit:
|
|
Py_XDECREF(fmt);
|
|
Py_XDECREF(args);
|
|
Py_XDECREF(py_password_required);
|
|
Py_XDECREF(py_min_password_len);
|
|
Py_XDECREF(py_manufacturer_id);
|
|
Py_XDECREF(py_library_description);
|
|
Py_XDECREF(py_crypto_token_description);
|
|
Py_XDECREF(py_db_token_description);
|
|
Py_XDECREF(py_fips_token_description);
|
|
Py_XDECREF(py_crypto_slot_description);
|
|
Py_XDECREF(py_db_slot_description);
|
|
Py_XDECREF(py_fips_slot_description);
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyTypeObject InitParametersType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.InitParameters", /* tp_name */
|
|
sizeof(InitParameters), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)InitParameters_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)InitParameters_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
InitParameters_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
InitParameters_methods, /* tp_methods */
|
|
InitParameters_members, /* tp_members */
|
|
InitParameters_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)InitParameters_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
InitParameters_new, /* tp_new */
|
|
};
|
|
|
|
/* ========================================================================== */
|
|
/* =========================== InitContext Class ============================ */
|
|
/* ========================================================================== */
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
InitContext_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
InitContext *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (InitContext *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->context = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
InitContext_dealloc(InitContext* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(InitContext_doc,
|
|
"An object representing NSSInitContext");
|
|
|
|
|
|
static PyObject *
|
|
InitContext_repr(InitContext *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject InitContextType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.InitContext", /* tp_name */
|
|
sizeof(InitContext), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)InitContext_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)InitContext_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
InitContext_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
0, /* tp_methods */
|
|
0, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0, /* tp_alloc */
|
|
0, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
InitContext_new_from_NSSInitContext(NSSInitContext *context)
|
|
{
|
|
InitContext *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (InitContext *) InitContext_new(&InitContextType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->context = context;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ========================= PKCS12DecodeItem Class ========================= */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_get_type(PKCS12DecodeItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->type);
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_get_has_key(PKCS12DecodeItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyBool_FromLong(self->has_key);
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_get_signed_cert_der(PKCS12DecodeItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_signed_cert_der);
|
|
return self->py_signed_cert_der;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_get_certificate(PKCS12DecodeItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_cert);
|
|
return self->py_cert;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_get_friendly_name(PKCS12DecodeItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_friendly_name);
|
|
return self->py_friendly_name;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_get_shroud_algorithm_id(PKCS12DecodeItem *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_INCREF(self->py_shroud_algorithm_id);
|
|
return self->py_shroud_algorithm_id;
|
|
}
|
|
|
|
static
|
|
PyGetSetDef PKCS12DecodeItem_getseters[] = {
|
|
{"type", (getter)PKCS12DecodeItem_get_type, (setter)NULL, "SEC OID tag indicating what type of PKCS12 item this is", NULL},
|
|
{"has_key", (getter)PKCS12DecodeItem_get_has_key, (setter)NULL, "boolean indicating if this is a cert with a private key", NULL},
|
|
{"signed_cert_der", (getter)PKCS12DecodeItem_get_signed_cert_der, (setter)NULL, "signed certificate DER data as SecItem object, or None if does not exist", NULL},
|
|
{"certificate", (getter)PKCS12DecodeItem_get_certificate, (setter)NULL, "certificate as Certificate object, or None if does not exist", NULL},
|
|
{"friendly_name", (getter)PKCS12DecodeItem_get_friendly_name, (setter)NULL, "friendly_name as unicode object, or None if does not exist", NULL},
|
|
{"shroud_algorithm_id", (getter)PKCS12DecodeItem_get_shroud_algorithm_id, (setter)NULL, "shroud algorithm id certificate as AlgorithmID object, or None if does not exist", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PKCS12DecodeItem_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_format_lines(PKCS12DecodeItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
obj = oid_tag_name_from_tag(self->type);
|
|
FMT_OBJ_AND_APPEND(lines, _("Type"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
switch (self->type) {
|
|
case SEC_OID_PKCS12_V1_CERT_BAG_ID:
|
|
if (self->has_key) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Certificate (has private key)"), level, fail);
|
|
} else {
|
|
FMT_LABEL_AND_APPEND(lines, _("Certificate"), level, fail);
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, NULL, self->py_cert, level+1, fail);
|
|
obj = SignedData_new_from_SECItem(&((SecItem *)self->py_signed_cert_der)->item);
|
|
FMT_OBJ_AND_APPEND(lines, _("Signature"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Friendly Name"), self->py_friendly_name, level, fail);
|
|
FMT_OBJ_AND_APPEND(lines, _("Encryption algorithm"), self->py_shroud_algorithm_id, level, fail);
|
|
break;
|
|
case SEC_OID_PKCS12_V1_KEY_BAG_ID:
|
|
case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
|
|
if (self->type == SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID) {
|
|
FMT_LABEL_AND_APPEND(lines, _("Key (shrouded)"), level, fail);
|
|
} else {
|
|
FMT_LABEL_AND_APPEND(lines, _("Key"), level, fail);
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Friendly Name"), self->py_friendly_name, level, fail);
|
|
FMT_OBJ_AND_APPEND(lines, _("Encryption algorithm"), self->py_shroud_algorithm_id, level, fail);
|
|
break;
|
|
default:
|
|
FMT_LABEL_AND_APPEND(lines, _("unknown bag type"), level, fail);
|
|
break;
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_format(PKCS12DecodeItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)PKCS12DecodeItem_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_str(PKCS12DecodeItem *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = PKCS12DecodeItem_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef PKCS12DecodeItem_methods[] = {
|
|
{"format_lines", (PyCFunction)PKCS12DecodeItem_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)PKCS12DecodeItem_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
PKCS12DecodeItem *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (PKCS12DecodeItem *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->type = SEC_OID_UNKNOWN;
|
|
self->has_key = PR_FALSE;
|
|
self->py_signed_cert_der = NULL;
|
|
self->py_cert = NULL;
|
|
self->py_friendly_name = NULL;
|
|
self->py_shroud_algorithm_id = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
PKCS12DecodeItem_traverse(PKCS12DecodeItem *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_signed_cert_der);
|
|
Py_VISIT(self->py_cert);
|
|
Py_VISIT(self->py_friendly_name);
|
|
Py_VISIT(self->py_shroud_algorithm_id);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
PKCS12DecodeItem_clear(PKCS12DecodeItem* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_signed_cert_der);
|
|
Py_CLEAR(self->py_cert);
|
|
Py_CLEAR(self->py_friendly_name);
|
|
Py_CLEAR(self->py_shroud_algorithm_id);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
PKCS12DecodeItem_dealloc(PKCS12DecodeItem* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
PKCS12DecodeItem_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PKCS12DecodeItem_doc,
|
|
"An object representing an item in a PKCS12 collection.\n\
|
|
Also known as a \"bag\"");
|
|
|
|
static int
|
|
PKCS12DecodeItem_init(PKCS12DecodeItem *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"arg", NULL};
|
|
PyObject *arg;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:PKCS12DecodeItem", kwlist,
|
|
&arg))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_repr(PKCS12DecodeItem *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PyTypeObject PKCS12DecodeItemType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PKCS12DecodeItem", /* tp_name */
|
|
sizeof(PKCS12DecodeItem), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PKCS12DecodeItem_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)PKCS12DecodeItem_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)PKCS12DecodeItem_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
PKCS12DecodeItem_doc, /* tp_doc */
|
|
(traverseproc)PKCS12DecodeItem_traverse, /* tp_traverse */
|
|
(inquiry)PKCS12DecodeItem_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PKCS12DecodeItem_methods, /* tp_methods */
|
|
PKCS12DecodeItem_members, /* tp_members */
|
|
PKCS12DecodeItem_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PKCS12DecodeItem_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PKCS12DecodeItem_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
PKCS12DecodeItem_new_from_SEC_PKCS12DecoderItem(const SEC_PKCS12DecoderItem *item)
|
|
{
|
|
PKCS12DecodeItem *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (PKCS12DecodeItem *) PKCS12DecodeItemType.tp_new(&PKCS12DecodeItemType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->type = item->type;
|
|
self->has_key = item->hasKey;
|
|
|
|
if (item->der) {
|
|
if ((self->py_signed_cert_der = SecItem_new_from_SECItem(item->der, SECITEM_signed_data)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
self->py_signed_cert_der = Py_None;
|
|
Py_INCREF(self->py_signed_cert_der);
|
|
}
|
|
|
|
if (item->friendlyName) {
|
|
if ((self->py_friendly_name = PyUnicode_DecodeUTF8((const char *)item->friendlyName->data,
|
|
item->friendlyName->len, NULL)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
self->py_friendly_name = Py_None;
|
|
Py_INCREF(self->py_friendly_name);
|
|
}
|
|
|
|
if (item->shroudAlg) {
|
|
if ((self->py_shroud_algorithm_id = AlgorithmID_new_from_SECAlgorithmID(item->shroudAlg)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
self->py_shroud_algorithm_id = Py_None;
|
|
Py_INCREF(self->py_shroud_algorithm_id);
|
|
}
|
|
|
|
if (item->type == SEC_OID_PKCS12_V1_CERT_BAG_ID) {
|
|
if ((self->py_cert = Certificate_new_from_signed_der_secitem(item->der)) == NULL) {
|
|
Py_CLEAR(self);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
self->py_cert = Py_None;
|
|
Py_INCREF(self->py_cert);
|
|
}
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ========================== PKCS12Decoder Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
static SECItem *
|
|
PKCS12_default_nickname_collision_callback(SECItem *old_nickname, PRBool *returned_cancel, void *arg)
|
|
{
|
|
char *nickname = NULL;
|
|
SECItem *returned_nickname = NULL;
|
|
CERTCertificate* cert = (CERTCertificate*)arg;
|
|
|
|
if (!returned_cancel || !cert) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((nickname = CERT_MakeCANickname(cert)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (old_nickname && old_nickname->data && old_nickname->len &&
|
|
PORT_Strlen(nickname) == old_nickname->len &&
|
|
PORT_Strncmp((char *)old_nickname->data, nickname, old_nickname->len) == 0) {
|
|
PORT_Free(nickname);
|
|
PORT_SetError(SEC_ERROR_CERT_NICKNAME_COLLISION);
|
|
PySys_WriteStderr("PKCS12_default_nickname_collision_callback: CERT_MakeCANickname() returned existing nickname\n");
|
|
return NULL;
|
|
}
|
|
|
|
if ((returned_nickname = PORT_ZNew(SECItem)) == NULL) {
|
|
PORT_Free(nickname);
|
|
return NULL;
|
|
}
|
|
|
|
returned_nickname->data = (unsigned char *)nickname;
|
|
returned_nickname->len = PORT_Strlen(nickname);
|
|
|
|
return returned_nickname;
|
|
}
|
|
|
|
static SECItem *
|
|
PKCS12_nickname_collision_callback(SECItem *old_nickname, PRBool *returned_cancel, void *arg)
|
|
{
|
|
CERTCertificate* cert = NULL;
|
|
PyGILState_STATE gstate;
|
|
PyObject *nickname_collision_callback = NULL;
|
|
PyObject *py_old_nickname = NULL;
|
|
PyObject *py_cert = NULL;
|
|
PyObject *result = NULL;
|
|
PyObject *new_args = NULL;
|
|
PyObject *py_new_nickname = NULL;
|
|
PyObject *py_new_nickname_utf8 = NULL;
|
|
PRBool cancel = PR_TRUE;
|
|
PyObject *py_cancel = NULL;
|
|
SECItem *returned_nickname = NULL;
|
|
|
|
gstate = PyGILState_Ensure();
|
|
|
|
TraceMessage("PKCS12_nickname_collision_callback: enter");
|
|
|
|
if ((nickname_collision_callback = get_thread_local("nickname_collision_callback")) == NULL) {
|
|
if (!PyErr_Occurred()) {
|
|
PySys_WriteStderr("PKCS12 nickname collision callback undefined\n");
|
|
} else {
|
|
PyErr_Print();
|
|
}
|
|
PyGILState_Release(gstate);
|
|
return NULL;
|
|
}
|
|
|
|
if (!old_nickname || !old_nickname->len || !old_nickname->data) {
|
|
py_old_nickname = Py_None;
|
|
Py_INCREF(py_old_nickname);
|
|
} else {
|
|
py_old_nickname = PyString_FromStringAndSize((char *)old_nickname->data, old_nickname->len);
|
|
}
|
|
|
|
cert = (CERTCertificate*)arg;
|
|
if ((py_cert = Certificate_new_from_CERTCertificate(cert)) == NULL) {
|
|
Py_DECREF(py_old_nickname);
|
|
return NULL;
|
|
}
|
|
/* Add reference because Certificate_dealloc will remove reference */
|
|
CERT_DupCertificate(((Certificate *)py_cert)->cert);
|
|
|
|
if ((new_args = PyTuple_New(2)) == NULL) {
|
|
PySys_WriteStderr("PKCS12 nickname collision callback: out of memory\n");
|
|
goto exit;
|
|
}
|
|
|
|
PyTuple_SetItem(new_args, 0, py_old_nickname);
|
|
PyTuple_SetItem(new_args, 1, py_cert);
|
|
|
|
if ((result = PyObject_CallObject(nickname_collision_callback, new_args)) == NULL) {
|
|
PySys_WriteStderr("exception in PKCS12 nickname collision callback\n");
|
|
PyErr_Print(); /* this also clears the error */
|
|
goto exit;
|
|
}
|
|
|
|
if (!PyTuple_Check(result) || PyTuple_Size(result) != 2) {
|
|
PySys_WriteStderr("Error, PKCS12 nickname collision callback expected tuple result with 2 values.\n");
|
|
goto exit;
|
|
}
|
|
|
|
py_new_nickname = PyTuple_GetItem(result, 0);
|
|
py_cancel = PyTuple_GetItem(result, 1);
|
|
|
|
if (!(PyString_Check(py_new_nickname) || PyUnicode_Check(py_new_nickname) ||
|
|
PyNone_Check(py_new_nickname))) {
|
|
PySys_WriteStderr("Error, PKCS12 nickname collision callback expected 1st returned item to be string or None.\n");
|
|
goto exit;
|
|
}
|
|
|
|
if (PyBool_Check(py_cancel)) {
|
|
cancel = PyBoolAsPRBool(py_cancel);
|
|
} else {
|
|
PySys_WriteStderr("Error, PKCS12 nickname collision callback expected 2nd returned item to be boolean.\n");
|
|
goto exit;
|
|
}
|
|
|
|
if (PyString_Check(py_new_nickname) || PyUnicode_Check(py_new_nickname)) {
|
|
if (PyString_Check(py_new_nickname)) {
|
|
py_new_nickname_utf8 = py_new_nickname;
|
|
Py_INCREF(py_new_nickname_utf8);
|
|
} else {
|
|
py_new_nickname_utf8 = PyUnicode_AsUTF8String(py_new_nickname);
|
|
}
|
|
|
|
if ((returned_nickname = PORT_New(SECItem)) == NULL) {
|
|
PyErr_NoMemory();
|
|
goto exit;
|
|
}
|
|
|
|
returned_nickname->data = (unsigned char *)PORT_Strdup(PyString_AsString(py_new_nickname_utf8));
|
|
returned_nickname->len = PyString_Size(py_new_nickname_utf8);
|
|
}
|
|
|
|
|
|
exit:
|
|
TraceMessage("PKCS12_nickname_collision_callback: exiting");
|
|
|
|
Py_XDECREF(new_args);
|
|
Py_XDECREF(result);
|
|
Py_XDECREF(py_new_nickname_utf8);
|
|
|
|
PyGILState_Release(gstate);
|
|
|
|
*returned_cancel = cancel;
|
|
return returned_nickname;
|
|
}
|
|
|
|
PyDoc_STRVAR(PKCS12_pkcs12_set_nickname_collision_callback_doc,
|
|
"pkcs12_set_nickname_collision_callback(callback)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
callback : function pointer\n\
|
|
The callback function\n\
|
|
\n\
|
|
When importing a certificate via a `PKCS12Decoder` object and the\n\
|
|
nickname is not set or collides with an existing nickname in the NSS\n\
|
|
database then this callback is invoked to resolve the problem. If no\n\
|
|
nickname collision callback has been set then an internal default\n\
|
|
callback will be used instead which calls the NSS function CERT_MakeCANickname\n\
|
|
(available in the Python binding as `Certificate.make_ca_nickname()`).\n\
|
|
\n\
|
|
The callback has the signature::\n\
|
|
\n\
|
|
nickname_collision_callback(old_nickname, cert) --> new_nickname, cancel\n\
|
|
\n\
|
|
old_nickname\n\
|
|
the preious nickname or None if previous did not exist\n\
|
|
cert\n\
|
|
the `Certificate` object being imported.\n\
|
|
\n\
|
|
The callback returns 2 values, the new nickname, and a boolean.\n\
|
|
\n\
|
|
new_nickname\n\
|
|
The new nickname to try or None\n\
|
|
\n\
|
|
cancel\n\
|
|
boolean indicating if collision resolution should be cancelled\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PKCS12_pkcs12_set_nickname_collision_callback(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *callback;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:pkcs12_set_nickname_collision_callback", &callback)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!PyCallable_Check(callback)) {
|
|
PyErr_SetString(PyExc_TypeError, "callback must be callable");
|
|
return NULL;
|
|
}
|
|
|
|
if (set_thread_local("nickname_collision_callback", callback) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static
|
|
PyGetSetDef PKCS12Decoder_getseters[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef PKCS12Decoder_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
PyDoc_STRVAR(PKCS12Decoder_database_import_doc,
|
|
"import()\n\
|
|
\n\
|
|
Import the contents of the `PKCS12Decoder` object into the current NSS database.\n\
|
|
\n\
|
|
During import if the certificate(s) in the `PKCS12Decoder` object does\n\
|
|
not have a nickname or there is a collision with an existing nickname\n\
|
|
then a callback will be invoked to provide a new nickname. See\n\
|
|
`pkcs12_set_nickname_collision_callback`.\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_database_import(PKCS12Decoder *self, PyObject *args)
|
|
{
|
|
SEC_PKCS12NicknameCollisionCallback nickname_callback = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (get_thread_local("nickname_collision_callback") == NULL) {
|
|
nickname_callback = PKCS12_default_nickname_collision_callback;
|
|
} else {
|
|
nickname_callback = PKCS12_nickname_collision_callback;
|
|
}
|
|
|
|
if (SEC_PKCS12DecoderValidateBags(self->decoder_ctx, nickname_callback) != SECSuccess) {
|
|
return set_nspr_error("PKCS12 decode validate bags failed");
|
|
}
|
|
|
|
if (SEC_PKCS12DecoderImportBags(self->decoder_ctx) != SECSuccess) {
|
|
return set_nspr_error("PKCS12 decode import bags failed");
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_format_lines(PKCS12Decoder *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
char *msg = NULL;
|
|
PyObject *obj = NULL;
|
|
Py_ssize_t i, n_items;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
n_items = PyTuple_Size(self->py_decode_items);
|
|
|
|
msg = PR_smprintf(_("%d PKCS12 Decode Items"), n_items);
|
|
FMT_LABEL_AND_APPEND(lines, msg, level, fail);
|
|
PR_smprintf_free(msg);
|
|
|
|
for (i = 0; i < n_items; i++) {
|
|
msg = PR_smprintf(_("Item %d"), i+1);
|
|
FMT_LABEL_AND_APPEND(lines, msg, level, fail);
|
|
PR_smprintf_free(msg);
|
|
|
|
obj = PKCS12Decoder_item(self, i);
|
|
CALL_FORMAT_LINES_AND_APPEND(lines, obj, level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if (i < n_items-1) { /* blank separator line */
|
|
FMT_LABEL_AND_APPEND(lines, NULL, level, fail);
|
|
}
|
|
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_format(PKCS12Decoder *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)PKCS12Decoder_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_str(PKCS12Decoder *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = PKCS12Decoder_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef PKCS12Decoder_methods[] = {
|
|
{"database_import", (PyCFunction)PKCS12Decoder_database_import, METH_NOARGS, PKCS12Decoder_database_import_doc},
|
|
{"format_lines", (PyCFunction)PKCS12Decoder_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)PKCS12Decoder_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Sequence Protocol ============================ */
|
|
|
|
static Py_ssize_t
|
|
PKCS12Decoder_length(PKCS12Decoder *self)
|
|
{
|
|
if (!self->py_decode_items) return 0;
|
|
return PyTuple_Size(self->py_decode_items);
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_item(PKCS12Decoder *self, register Py_ssize_t i)
|
|
{
|
|
PyObject *py_decode_item = NULL;
|
|
|
|
if (!self->py_decode_items) {
|
|
return PyErr_Format(PyExc_ValueError, "%s is uninitialized", Py_TYPE(self)->tp_name);
|
|
}
|
|
py_decode_item = PyTuple_GetItem(self->py_decode_items, i);
|
|
Py_XINCREF(py_decode_item);
|
|
return py_decode_item;
|
|
}
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
PKCS12Decoder *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (PKCS12Decoder *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->decoder_ctx = NULL;
|
|
self->py_decode_items = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static int
|
|
PKCS12Decoder_traverse(PKCS12Decoder *self, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(self->py_decode_items);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
PKCS12Decoder_clear(PKCS12Decoder* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_CLEAR(self->py_decode_items);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
PKCS12Decoder_dealloc(PKCS12Decoder* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->decoder_ctx) {
|
|
SEC_PKCS12DecoderFinish(self->decoder_ctx);
|
|
}
|
|
|
|
PKCS12Decoder_clear(self);
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(PKCS12Decoder_doc,
|
|
"PKCS12Decoder(file, password, slot=None)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
file : file name or file object\n\
|
|
pkcs12 input data.\n\
|
|
\n\
|
|
* If string treat as file path to open and read.\n\
|
|
* If file object read from the file object.\n\
|
|
password : string\n\
|
|
The password protecting the PKCS12 contents\n\
|
|
slot : `PK11Slot` object\n\
|
|
The PK11 slot to use. If None defaults to internal\n\
|
|
slot, see `nss.get_internal_key_slot()`\n\
|
|
\n\
|
|
");
|
|
|
|
static int
|
|
PKCS12Decoder_init(PKCS12Decoder *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"file", "password", "slot", NULL};
|
|
PyObject *file_arg = NULL;
|
|
PyObject *py_file_contents = NULL;
|
|
PyObject *py_slot = Py_None;
|
|
char *utf8_password = NULL;
|
|
size_t utf8_password_len = 0;
|
|
unsigned char *ucs2_password = NULL;
|
|
unsigned int ucs2_password_alloc_len = 0;
|
|
unsigned int ucs2_password_len = 0;
|
|
SECItem ucs2_password_item;
|
|
|
|
char *slot_password = NULL;
|
|
PK11SlotInfo *slot = NULL;
|
|
int num_decode_items = 0;
|
|
const SEC_PKCS12DecoderItem *decoder_item = NULL;
|
|
PyObject *py_decode_item = NULL;
|
|
int item_idx;
|
|
int result = 0;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oes|O&:PKCS12Decoder", kwlist,
|
|
&file_arg, "utf-8", &utf8_password,
|
|
PK11SlotOrNoneConvert, &py_slot)) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
if ((py_file_contents = read_data_from_file(file_arg)) == NULL) {
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* The +1 for the utf8 password is for the null terminator which is used
|
|
* in the computation of the symetric key. Therefore the conversion to
|
|
* ucs2 must include the null terminator. It's safe for us to read the
|
|
* null terminator at the end of the string Python provides because Python
|
|
* always provides a 1 byte null terminator for all of it's string allocations.
|
|
*/
|
|
utf8_password_len = strlen(utf8_password) + 1;
|
|
ucs2_password_alloc_len = utf8_password_len * 2;
|
|
|
|
if ((ucs2_password = PyMem_Malloc(ucs2_password_alloc_len)) == NULL) {
|
|
PyErr_NoMemory();
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
if (!PORT_UCS2_UTF8Conversion(PR_TRUE, (unsigned char *)utf8_password, utf8_password_len,
|
|
ucs2_password, ucs2_password_alloc_len, &ucs2_password_len)) {
|
|
PyErr_SetString(PyExc_ValueError, "password conversion to UCS2 failed");
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
if (PyNone_Check(py_slot)) {
|
|
slot = PK11_GetInternalKeySlot();
|
|
} else {
|
|
slot = ((PK11Slot *)py_slot)->slot;
|
|
}
|
|
|
|
ucs2_password_item.data = ucs2_password;
|
|
ucs2_password_item.len = ucs2_password_len;
|
|
if ((self->decoder_ctx = SEC_PKCS12DecoderStart(&ucs2_password_item,
|
|
slot,
|
|
slot_password,
|
|
NULL, NULL, NULL, NULL, NULL)) == NULL) {
|
|
set_nspr_error("PKCS12 decoder start failed");
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* decode the item */
|
|
if (SEC_PKCS12DecoderUpdate(self->decoder_ctx,
|
|
(unsigned char *)PyString_AS_STRING(py_file_contents),
|
|
PyString_GET_SIZE(py_file_contents)) != SECSuccess) {
|
|
set_nspr_error("PKCS12 decoding failed");
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* does the blob authenticate properly? */
|
|
if ((SEC_PKCS12DecoderVerify(self->decoder_ctx) != SECSuccess)) {
|
|
set_nspr_error("PKCS12 decode not verified");
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
if (SEC_PKCS12DecoderIterateInit(self->decoder_ctx) != SECSuccess) {
|
|
set_nspr_error("PKCS12 item iteration failed");
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
num_decode_items = 0;
|
|
while (SEC_PKCS12DecoderIterateNext(self->decoder_ctx, &decoder_item) == SECSuccess) {
|
|
num_decode_items++;
|
|
}
|
|
if ((self->py_decode_items = PyTuple_New(num_decode_items)) == NULL) {
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
if (SEC_PKCS12DecoderIterateInit(self->decoder_ctx) != SECSuccess) {
|
|
set_nspr_error("PKCS12 item iteration failed");
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
|
|
for (item_idx = 0;
|
|
SEC_PKCS12DecoderIterateNext(self->decoder_ctx, &decoder_item) == SECSuccess;
|
|
item_idx++) {
|
|
if ((py_decode_item = PKCS12DecodeItem_new_from_SEC_PKCS12DecoderItem(decoder_item)) == NULL) {
|
|
result = -1;
|
|
goto exit;
|
|
}
|
|
PyTuple_SetItem(self->py_decode_items, item_idx, py_decode_item);
|
|
}
|
|
|
|
exit:
|
|
if (!py_slot && slot) {
|
|
PK11_FreeSlot(slot);
|
|
}
|
|
|
|
if (utf8_password)
|
|
PyMem_Free(utf8_password);
|
|
if (ucs2_password)
|
|
PyMem_Free(ucs2_password);
|
|
if (py_file_contents)
|
|
Py_DECREF(py_file_contents);
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyObject *
|
|
PKCS12Decoder_repr(PKCS12Decoder *self)
|
|
{
|
|
return PyString_FromFormat("<%s object at %p>",
|
|
Py_TYPE(self)->tp_name, self);
|
|
}
|
|
|
|
static PySequenceMethods PKCS12Decoder_as_sequence = {
|
|
(lenfunc)PKCS12Decoder_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)PKCS12Decoder_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyTypeObject PKCS12DecoderType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.PKCS12Decoder", /* tp_name */
|
|
sizeof(PKCS12Decoder), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)PKCS12Decoder_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
(reprfunc)PKCS12Decoder_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&PKCS12Decoder_as_sequence, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)PKCS12Decoder_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
|
PKCS12Decoder_doc, /* tp_doc */
|
|
(traverseproc)PKCS12Decoder_traverse, /* tp_traverse */
|
|
(inquiry)PKCS12Decoder_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
PKCS12Decoder_methods, /* tp_methods */
|
|
PKCS12Decoder_members, /* tp_members */
|
|
PKCS12Decoder_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)PKCS12Decoder_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
PKCS12Decoder_new, /* tp_new */
|
|
};
|
|
|
|
|
|
/* ========================================================================== */
|
|
/* ======================== CertVerifyLogNode Class ========================= */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_get_certificate(CertVerifyLogNode *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return Certificate_new_from_CERTCertificate(self->node.cert);
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_get_error(CertVerifyLogNode *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->node.error);
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_get_depth(CertVerifyLogNode *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->node.depth);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef CertVerifyLogNode_getseters[] = {
|
|
{"certificate", (getter)CertVerifyLogNode_get_certificate, NULL,
|
|
"returns the certificate as a `Certificate` object", NULL},
|
|
{"error", (getter)CertVerifyLogNode_get_error, NULL,
|
|
"returns the error code as an integer", NULL},
|
|
{"depth", (getter)CertVerifyLogNode_get_depth, NULL,
|
|
"returns the chain position as an integer", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CertVerifyLogNode_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
CertVerifyLogNodeError_format_lines(CertVerifyLogNode *self, int level, PyObject *lines)
|
|
{
|
|
RepresentationKind repr_kind = AsEnumName;
|
|
PyObject *obj = NULL;
|
|
PyObject *py_cert = NULL;
|
|
NSPRErrorDesc const *error_desc = NULL;
|
|
CERTVerifyLogNode *node = NULL;
|
|
|
|
if (!lines) {
|
|
goto fail;
|
|
}
|
|
|
|
node = &self->node;
|
|
|
|
if ((error_desc = lookup_nspr_error(node->error)) == NULL) {
|
|
if ((obj = PyString_FromFormat(_("Unknown error code %ld (%#lx)"),
|
|
node->error, node->error)) == NULL) {
|
|
goto fail;
|
|
}
|
|
} else {
|
|
if ((obj = PyString_FromFormat("[%s] %s",
|
|
error_desc->name,
|
|
error_desc->string)) == NULL) {
|
|
goto fail;
|
|
}
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Error"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
switch (node->error) {
|
|
case SEC_ERROR_INADEQUATE_KEY_USAGE: {
|
|
unsigned int flags = (unsigned int)node->arg;
|
|
|
|
if ((obj = key_usage_flags(flags, repr_kind)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Inadequate Key Usage"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
} break;
|
|
case SEC_ERROR_INADEQUATE_CERT_TYPE: {
|
|
unsigned int flags = (unsigned int)node->arg;
|
|
|
|
if ((obj = cert_type_flags(flags, repr_kind)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Inadequate Cert Type"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
} break;
|
|
case SEC_ERROR_UNKNOWN_ISSUER:
|
|
case SEC_ERROR_UNTRUSTED_ISSUER:
|
|
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
|
|
if ((py_cert = Certificate_new_from_CERTCertificate(node->cert)) == NULL) {
|
|
goto fail;
|
|
}
|
|
if ((obj = Certificate_get_issuer((Certificate *)py_cert, NULL)) == NULL) {
|
|
goto fail;
|
|
}
|
|
Py_CLEAR(py_cert);
|
|
|
|
FMT_OBJ_AND_APPEND(lines, _("Issuer"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(py_cert);
|
|
Py_XDECREF(obj);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_format_lines(CertVerifyLogNode *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
Certificate *py_cert = NULL;
|
|
CERTVerifyLogNode *node = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
node = &self->node;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
FMT_LABEL_AND_APPEND(lines, _("Certificate"), level, fail);
|
|
|
|
if ((py_cert = (Certificate *)Certificate_new_from_CERTCertificate(node->cert)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if (Certificate_summary_format_lines(py_cert, level+1, lines) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if ((obj = PyInt_FromLong(node->depth)) == NULL){
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Depth"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if (CertVerifyLogNodeError_format_lines(self, level, lines) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(py_cert);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_format(CertVerifyLogNode *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)CertVerifyLogNode_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_str(CertVerifyLogNode *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = CertVerifyLogNode_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
|
|
static PyMethodDef CertVerifyLogNode_methods[] = {
|
|
{"format_lines", (PyCFunction)CertVerifyLogNode_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)CertVerifyLogNode_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CertVerifyLogNode *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CertVerifyLogNode *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(&self->node, 0, sizeof(self->node));
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
CertVerifyLogNode_dealloc(CertVerifyLogNode* self)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (self->node.cert) {
|
|
CERT_DestroyCertificate(self->node.cert);
|
|
}
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CertVerifyLogNode_doc,
|
|
"CertVerifyLogNode()\n\
|
|
\n\
|
|
An object detailing specific diagnostic information concerning\n\
|
|
a single failure during certification validation.\n\
|
|
These are collected in a `CertVerifyLog` object.\n\
|
|
");
|
|
|
|
static PyTypeObject CertVerifyLogNodeType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CertVerifyLogNode", /* tp_name */
|
|
sizeof(CertVerifyLogNode), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CertVerifyLogNode_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)CertVerifyLogNode_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
CertVerifyLogNode_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CertVerifyLogNode_methods, /* tp_methods */
|
|
CertVerifyLogNode_members, /* tp_members */
|
|
CertVerifyLogNode_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CertVerifyLogNode_new, /* tp_new */
|
|
};
|
|
|
|
static PyObject *
|
|
CertVerifyLogNode_new_from_CERTVerifyLogNode(CERTVerifyLogNode *node)
|
|
{
|
|
CertVerifyLogNode *self = NULL;
|
|
|
|
TraceObjNewEnter(NULL);
|
|
|
|
if ((self = (CertVerifyLogNode *) CertVerifyLogNodeType.tp_new(&CertVerifyLogNodeType, NULL, NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
self->node.cert = CERT_DupCertificate(node->cert);
|
|
self->node.error = node->error;
|
|
self->node.depth = node->depth;
|
|
self->node.arg = node->arg;
|
|
self->node.next = NULL;
|
|
self->node.prev = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
|
|
return (PyObject *) self;
|
|
}
|
|
/* ========================================================================== */
|
|
/* ========================== CertVerifyLog Class =========================== */
|
|
/* ========================================================================== */
|
|
|
|
/* ============================ Attribute Access ============================ */
|
|
|
|
static PyObject *
|
|
CertVerifyLog_get_count(CertVerifyLog *self, void *closure)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return PyInt_FromLong(self->log.count);
|
|
}
|
|
|
|
static
|
|
PyGetSetDef CertVerifyLog_getseters[] = {
|
|
{"count", (getter)CertVerifyLog_get_count, NULL,
|
|
"number of validation errors", NULL},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef CertVerifyLog_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Class Methods ============================= */
|
|
|
|
static PyObject *
|
|
CertVerifyLog_format_lines(CertVerifyLog *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"level", NULL};
|
|
int level = 0;
|
|
PyObject *lines = NULL;
|
|
PyObject *obj = NULL;
|
|
Py_ssize_t i, n_items;
|
|
unsigned int depth = ~0;
|
|
CertVerifyLogNode *py_node = NULL;
|
|
Certificate *py_cert = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:format_lines", kwlist, &level))
|
|
return NULL;
|
|
|
|
if ((lines = PyList_New(0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((obj = PyInt_FromLong(self->log.count)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_OBJ_AND_APPEND(lines, _("Validation Errors"), obj, level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
|
|
n_items = CertVerifyLog_length(self);
|
|
|
|
for (i = 0; i < n_items; i++) {
|
|
CERTVerifyLogNode *node = NULL;
|
|
|
|
py_node = (CertVerifyLogNode *)CertVerifyLog_item(self, i);
|
|
node = &py_node->node;
|
|
|
|
if (depth != node->depth) {
|
|
depth = node->depth;
|
|
|
|
if ((obj = PyString_FromFormat(_("Certificate at chain depth %u"), node->depth)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_LABEL_AND_APPEND(lines, PyString_AsString(obj), level, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if ((py_cert = (Certificate *)Certificate_new_from_CERTCertificate(node->cert)) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
if (Certificate_summary_format_lines(py_cert, level+1, lines) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
Py_CLEAR(py_cert);
|
|
|
|
/* Add blank line between cert and errors */
|
|
FMT_LABEL_AND_APPEND(lines, NULL, level, fail);
|
|
}
|
|
|
|
if ((obj = PyString_FromFormat(_("Validation Error #%u"), i+1)) == NULL) {
|
|
goto fail;
|
|
}
|
|
FMT_LABEL_AND_APPEND(lines, PyString_AsString(obj), level+1, fail);
|
|
Py_CLEAR(obj);
|
|
|
|
if (CertVerifyLogNodeError_format_lines(py_node, level+2, lines) == NULL) {
|
|
goto fail;
|
|
}
|
|
|
|
Py_CLEAR(py_node);
|
|
|
|
//if (i < n_items-1) { /* blank separator line */
|
|
// FMT_LABEL_AND_APPEND(lines, NULL, level, fail);
|
|
//}
|
|
|
|
}
|
|
|
|
return lines;
|
|
fail:
|
|
Py_XDECREF(py_node);
|
|
Py_XDECREF(py_cert);
|
|
Py_XDECREF(obj);
|
|
Py_XDECREF(lines);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLog_format(CertVerifyLog *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
return format_from_lines((format_lines_func)CertVerifyLog_format_lines, (PyObject *)self, args, kwds);
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLog_str(CertVerifyLog *self)
|
|
{
|
|
PyObject *py_formatted_result = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
py_formatted_result = CertVerifyLog_format(self, empty_tuple, NULL);
|
|
return py_formatted_result;
|
|
|
|
}
|
|
|
|
static PyMethodDef CertVerifyLog_methods[] = {
|
|
{"format_lines", (PyCFunction)CertVerifyLog_format_lines, METH_VARARGS|METH_KEYWORDS, generic_format_lines_doc},
|
|
{"format", (PyCFunction)CertVerifyLog_format, METH_VARARGS|METH_KEYWORDS, generic_format_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* =========================== Sequence Protocol ============================ */
|
|
static Py_ssize_t
|
|
CertVerifyLog_length(CertVerifyLog *self)
|
|
{
|
|
return self->log.count;
|
|
}
|
|
|
|
static PyObject *
|
|
CertVerifyLog_item(CertVerifyLog *self, register Py_ssize_t i)
|
|
{
|
|
CERTVerifyLogNode *node = NULL;
|
|
Py_ssize_t index;
|
|
|
|
for (node = self->log.head, index = 0;
|
|
node && index <= i;
|
|
node = node->next, index++) {
|
|
if (i == index) {
|
|
return CertVerifyLogNode_new_from_CERTVerifyLogNode(node);
|
|
}
|
|
}
|
|
|
|
PyErr_SetString(PyExc_IndexError, "CertVerifyLog index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* =========================== Class Construction =========================== */
|
|
|
|
static PyObject *
|
|
CertVerifyLog_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
{
|
|
CertVerifyLog *self;
|
|
|
|
TraceObjNewEnter(type);
|
|
|
|
if ((self = (CertVerifyLog *)type->tp_alloc(type, 0)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((self->log.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL) {
|
|
type->tp_free(self);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
self->log.count = 0;
|
|
self->log.head = NULL;
|
|
self->log.tail = NULL;
|
|
|
|
TraceObjNewLeave(self);
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static void
|
|
CertVerifyLog_dealloc(CertVerifyLog* self)
|
|
{
|
|
CERTVerifyLogNode *node = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
for (node = self->log.head; node; node = node->next) {
|
|
if (node->cert) {
|
|
CERT_DestroyCertificate(node->cert);
|
|
}
|
|
}
|
|
PORT_FreeArena(self->log.arena, PR_FALSE);
|
|
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
PyDoc_STRVAR(CertVerifyLog_doc,
|
|
"CertVerifyLog()\n\
|
|
\n\
|
|
An object which collects diagnostic information during\n\
|
|
certification validation.\n\
|
|
");
|
|
|
|
static PySequenceMethods CertVerifyLog_as_sequence = {
|
|
(lenfunc)CertVerifyLog_length, /* sq_length */
|
|
0, /* sq_concat */
|
|
0, /* sq_repeat */
|
|
(ssizeargfunc)CertVerifyLog_item, /* sq_item */
|
|
0, /* sq_slice */
|
|
0, /* sq_ass_item */
|
|
0, /* sq_ass_slice */
|
|
0, /* sq_contains */
|
|
0, /* sq_inplace_concat */
|
|
0, /* sq_inplace_repeat */
|
|
};
|
|
|
|
static PyTypeObject CertVerifyLogType = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /* ob_size */
|
|
"nss.nss.CertVerifyLog", /* tp_name */
|
|
sizeof(CertVerifyLog), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)CertVerifyLog_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
&CertVerifyLog_as_sequence, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
(reprfunc)CertVerifyLog_str, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
CertVerifyLog_doc, /* tp_doc */
|
|
(traverseproc)0, /* tp_traverse */
|
|
(inquiry)0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
CertVerifyLog_methods, /* tp_methods */
|
|
CertVerifyLog_members, /* tp_members */
|
|
CertVerifyLog_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0, /* tp_alloc */
|
|
CertVerifyLog_new, /* tp_new */
|
|
};
|
|
/* ========================== PK11 Methods =========================== */
|
|
|
|
static char *
|
|
PK11_password_callback(PK11SlotInfo *slot, PRBool retry, void *arg)
|
|
{
|
|
Py_ssize_t n_base_args = 2;
|
|
PyGILState_STATE gstate;
|
|
PyObject *password_callback = NULL;
|
|
PyObject *pin_args = arg; /* borrowed reference, don't decrement */
|
|
PyObject *py_slot = NULL;
|
|
PyObject *item;
|
|
PyObject *result = NULL;
|
|
PyObject *new_args = NULL;
|
|
Py_ssize_t argc;
|
|
int i, j;
|
|
char *password = NULL;
|
|
|
|
gstate = PyGILState_Ensure();
|
|
|
|
TraceMessage("PK11_password_callback: enter");
|
|
|
|
if ((password_callback = get_thread_local("password_callback")) == NULL) {
|
|
if (!PyErr_Occurred()) {
|
|
PySys_WriteStderr("PK11 password callback undefined\n");
|
|
} else {
|
|
PyErr_Print();
|
|
}
|
|
PyGILState_Release(gstate);
|
|
return NULL;
|
|
}
|
|
|
|
argc = n_base_args;
|
|
if (pin_args) {
|
|
if (PyTuple_Check(pin_args)) {
|
|
argc += PyTuple_Size(pin_args);
|
|
} else {
|
|
PySys_WriteStderr("Error, PK11 password callback expected args to be tuple\n");
|
|
PyErr_Print();
|
|
}
|
|
}
|
|
|
|
if ((new_args = PyTuple_New(argc)) == NULL) {
|
|
PySys_WriteStderr("PK11 password callback: out of memory\n");
|
|
goto exit;
|
|
}
|
|
|
|
if ((py_slot = PK11Slot_new_from_PK11SlotInfo(slot)) == NULL) {
|
|
PySys_WriteStderr("exception in PK11 password callback\n");
|
|
PyErr_Print();
|
|
goto exit;
|
|
}
|
|
/*
|
|
* Every NSS function that returns a slot has it's reference count
|
|
* incremented. We wrap that slot in a PK11Slot Python object and
|
|
* when the PK11Slot Python object is deallocated we decrement the
|
|
* NSS slot reference count by calling PK11_FreeSlot.
|
|
*
|
|
* However in this callback we're not returned a slot, rather we
|
|
* are passed a slot, it's reference count has not been
|
|
* incremented. But we still wrap the NSS slot with a PK11Slot
|
|
* Python object which when deallocated will decrement the NSS
|
|
* slot reference count. Therefore we increment the NSS slots
|
|
* reference count by calling PK11_ReferenceSlot.
|
|
*/
|
|
PK11_ReferenceSlot(((PK11Slot *)py_slot)->slot);
|
|
|
|
PyTuple_SetItem(new_args, 0, py_slot);
|
|
PyTuple_SetItem(new_args, 1, PyBool_FromLong(retry));
|
|
|
|
for (i = n_base_args, j = 0; i < argc; i++, j++) {
|
|
item = PyTuple_GetItem(pin_args, j);
|
|
Py_INCREF(item);
|
|
PyTuple_SetItem(new_args, i, item);
|
|
}
|
|
|
|
if ((result = PyObject_CallObject(password_callback, new_args)) == NULL) {
|
|
PySys_WriteStderr("exception in PK11 password callback\n");
|
|
PyErr_Print(); /* this also clears the error */
|
|
goto exit;
|
|
}
|
|
|
|
if (!(PyString_Check(result) || PyUnicode_Check(result))) {
|
|
PySys_WriteStderr("Error, PK11 password callback expected string result.\n");
|
|
goto exit;
|
|
}
|
|
|
|
password = PORT_Strdup(PyString_AsString(result));
|
|
|
|
exit:
|
|
TraceMessage("PK11_password_callback: exiting");
|
|
|
|
Py_XDECREF(new_args);
|
|
Py_XDECREF(result);
|
|
|
|
PyGILState_Release(gstate);
|
|
|
|
return password;
|
|
}
|
|
|
|
/* ========================================================================== */
|
|
/* ========================= Global PK11 Functions ========================== */
|
|
/* ========================================================================== */
|
|
|
|
PyDoc_STRVAR(pk11_set_password_callback_doc,
|
|
"set_password_callback(callback)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
callback : function pointer\n\
|
|
The callback function\n\
|
|
\n\
|
|
The callback has the signature::\n\
|
|
\n\
|
|
password_callback(slot, retry, [user_data1, ...])\n\
|
|
\n\
|
|
slot\n\
|
|
PK11Slot object\n\
|
|
retry\n\
|
|
boolean indicating if this is a retry\n\
|
|
user_dataN\n\
|
|
zero or more caller supplied optional parameters\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_set_password_callback(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *callback = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:set_password_callback", &callback)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!PyCallable_Check(callback)) {
|
|
PyErr_SetString(PyExc_TypeError, "callback must be callable");
|
|
return NULL;
|
|
}
|
|
|
|
if (set_thread_local("password_callback", callback) < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
PK11_SetPasswordFunc(PK11_password_callback);
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_list_certs_doc,
|
|
"list_certs(type, [user_data1, ...]) -> (`Certificate`, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
type : int\n\
|
|
PK11CertList* enumerated constant.\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Given the type of certificates to list return a tuple of `Certificate`\n\
|
|
objects matching that type.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_list_certs(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
int type = PK11CertListAll;
|
|
CERTCertList *cert_list = NULL;
|
|
PyObject *tuple = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "i:list_certs", &type)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((cert_list = PK11_ListCerts(type, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
tuple = CERTCertList_to_tuple(cert_list);
|
|
CERT_DestroyCertList(cert_list);
|
|
return tuple;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_find_certs_from_email_addr_doc,
|
|
"find_certs_from_email_addr(email, [user_data1, ...]) -> (`Certificate`, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
email : string\n\
|
|
email address.\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Given an email address return a tuple of `Certificate`\n\
|
|
objects containing that address.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_find_certs_from_email_addr(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
char *email_addr = NULL;
|
|
CERTCertList *cert_list = NULL;
|
|
PyObject *tuple = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "s:find_certs_from_email_addr",
|
|
&email_addr)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((cert_list = PK11_FindCertsFromEmailAddress(email_addr, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
tuple = CERTCertList_to_tuple(cert_list);
|
|
CERT_DestroyCertList(cert_list);
|
|
return tuple;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_find_certs_from_nickname_doc,
|
|
"find_certs_from_nickname(email, [user_data1, ...]) -> (`Certificate`, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
nickname : string\n\
|
|
certificate nickname.\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Given a certificate nickname return a tuple of `Certificate`\n\
|
|
objects matching that nickname.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_find_certs_from_nickname(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
char *nickname = NULL;
|
|
CERTCertList *cert_list = NULL;
|
|
PyObject *tuple = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "s:find_certs_from_nickname",
|
|
&nickname)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((cert_list = PK11_FindCertsFromNickname(nickname, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
tuple = CERTCertList_to_tuple(cert_list);
|
|
CERT_DestroyCertList(cert_list);
|
|
return tuple;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_find_cert_from_nickname_doc,
|
|
"find_cert_from_nickname(nickname, [user_data1, ...]) -> Certificate\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
nickname : string\n\
|
|
certificate nickname to search for\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
A nickname is an alias for a certificate subject. There may be\n\
|
|
multiple certificates with the same subject, and hence the same\n\
|
|
nickname. This function will return the newest certificate that\n\
|
|
matches the subject, based on the NotBefore / NotAfter fields of the\n\
|
|
certificate.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_find_cert_from_nickname(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
char *nickname = NULL;
|
|
CERTCertificate *cert = NULL;
|
|
PyObject *py_cert = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "s:find_cert_from_nickname", &nickname)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((cert = PK11_FindCertFromNickname(nickname, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
if ((py_cert = Certificate_new_from_CERTCertificate(cert)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return py_cert;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_find_key_by_any_cert_doc,
|
|
"find_key_by_any_cert(cert, [user_data1, ...]) -> Certificate\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cert : Certificate object\n\
|
|
certificate whose private key is being searched for\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Finds the private key associated with a specified certificate in any\n\
|
|
available slot.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_find_key_by_any_cert(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
Certificate *py_cert = NULL;
|
|
PyObject *pin_args = NULL;
|
|
SECKEYPrivateKey *private_key;
|
|
PyObject *py_private_key = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "O!:find_key_by_any_cert",
|
|
&CertificateType, &py_cert)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((private_key = PK11_FindKeyByAnyCert(py_cert->cert, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
if ((py_private_key = PrivateKey_new_from_SECKEYPrivateKey(private_key)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return py_private_key;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_generate_random_doc,
|
|
"generate_random(num_bytes) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
num_bytes : integer\n\
|
|
Number of num_bytes to generate (must be non-negative)\n\
|
|
\n\
|
|
Generates random data..\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_generate_random(PyObject *self, PyObject *args)
|
|
{
|
|
int num_bytes;
|
|
unsigned char *buf;
|
|
SECStatus status;
|
|
PyObject *res;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "i:generate_random", &num_bytes))
|
|
return NULL;
|
|
|
|
if (num_bytes < 0) {
|
|
PyErr_SetString(PyExc_ValueError, "byte count must be non-negative");
|
|
return NULL;
|
|
}
|
|
|
|
buf = PyMem_Malloc(num_bytes);
|
|
if (buf == NULL) {
|
|
return PyErr_NoMemory();
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
status = PK11_GenerateRandom(buf, num_bytes);
|
|
Py_END_ALLOW_THREADS
|
|
if (status != SECSuccess) {
|
|
PyMem_Free(buf);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
res = PyString_FromStringAndSize((char *)buf, num_bytes);
|
|
PyMem_Free(buf);
|
|
return res;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_pk11_need_pw_init_doc,
|
|
"pk11_need_pw_init() -> bool\n\
|
|
\n\
|
|
Returns True if the internal slot needs to be initialized, False otherwise.\n\
|
|
\n\
|
|
The internal slot token should be initalized if:\n\
|
|
\n\
|
|
The token is not initialized\n\
|
|
\n\
|
|
`PK11Slot.need_login()` == True and `PK11Slot.need_user_init()` == True\n\
|
|
\n\
|
|
Or\n\
|
|
\n\
|
|
The token has a NULL password.\n\
|
|
\n\
|
|
`PK11Slot.need_login()` == False and `PK11Slot.need_user_init()` == False\n\
|
|
\n\
|
|
+------------------+------------------------+---------------------+\n\
|
|
|CKF_LOGIN_REQUIRED|CKF_USER_PIN_INITIALIZED|CKF_TOKEN_INITIALIZED|\n\
|
|
+==================+========================+=====================+\n\
|
|
| False | False | True |\n\
|
|
+------------------+------------------------+---------------------+\n\
|
|
| True | False | False |\n\
|
|
+------------------+------------------------+---------------------+\n\
|
|
| False | True | True |\n\
|
|
+------------------+------------------------+---------------------+\n\
|
|
| True | True | True |\n\
|
|
+------------------+------------------------+---------------------+\n\
|
|
\n\
|
|
`PK11Slot.need_login()` == CKF_LOGIN_REQUIRED\n\
|
|
\n\
|
|
`PK11Slot.need_user_init()` == !CKF_USER_PIN_INITIALIZED\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_pk11_need_pw_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_NeedPWInit())
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
|
|
PyDoc_STRVAR(pk11_pk11_token_exists_doc,
|
|
"pk11_token_exists(mechanism) -> bool\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Return True if a token is available which can perform\n\
|
|
the desired mechanism, False otherwise.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_pk11_token_exists(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:pk11_token_exists",
|
|
&mechanism))
|
|
return NULL;
|
|
|
|
if (PK11_TokenExists(mechanism))
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_pk11_is_fips_doc,
|
|
"pk11_is_fips() -> bool\n\
|
|
\n\
|
|
Returns True if the internal module has FIPS enabled, False otherwise.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_pk11_is_fips(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
if (PK11_IsFIPS())
|
|
Py_RETURN_TRUE;
|
|
else
|
|
Py_RETURN_FALSE;
|
|
}
|
|
/* ============================== Module Methods ============================= */
|
|
|
|
PyDoc_STRVAR(nss_nss_is_initialized_doc,
|
|
"nss_is_initialized() --> bool\n\
|
|
\n\
|
|
Returns whether Network Security Services has already been initialized or not.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_is_initialized(PyObject *self, PyObject *args)
|
|
{
|
|
PRBool is_init;
|
|
TraceMethodEnter(self);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
is_init = NSS_IsInitialized();
|
|
Py_END_ALLOW_THREADS
|
|
|
|
if (is_init) {
|
|
Py_RETURN_TRUE;
|
|
} else {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_init_doc,
|
|
"nss_init(cert_dir)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cert_dir : string\n\
|
|
Pathname of the directory where the certificate, key, and\n\
|
|
security module databases reside.\n\
|
|
\n\
|
|
Sets up configuration files and performs other tasks required to run\n\
|
|
Network Security Services. `nss.nss_init()` differs from\n\
|
|
`nss.nss_init_read_write()` because the internal PK11 slot (see\n\
|
|
`nss.get_internal_slot()`) is created in Read Only (RO) mode as\n\
|
|
opposed to Read Write (RW) mode.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_init(PyObject *self, PyObject *args)
|
|
{
|
|
char *cert_dir;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "es:nss_init",
|
|
"utf-8", &cert_dir)) {
|
|
return NULL;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (NSS_Init(cert_dir) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
PyMem_Free(cert_dir);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
PyMem_Free(cert_dir);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_init_read_write_doc,
|
|
"nss_init_read_write(cert_dir)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cert_dir : string\n\
|
|
Pathname of the directory where the certificate, key, and\n\
|
|
security module databases reside.\n\
|
|
\n\
|
|
Sets up configuration files and performs other tasks required to run\n\
|
|
Network Security Services. `nss.nss_init_read_write()` differs from\n\
|
|
`nss.nss_init()` because the internal PK11 slot (see\n\
|
|
`nss.get_internal_slot()`) is created in Read Write (RW) mode as\n\
|
|
opposed to Read Only (RO) mode.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_init_read_write(PyObject *self, PyObject *args)
|
|
{
|
|
char *cert_dir;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "es:nss_init_read_write",
|
|
"utf-8", &cert_dir)) {
|
|
return NULL;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (NSS_InitReadWrite(cert_dir) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
PyMem_Free(cert_dir);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
PyMem_Free(cert_dir);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_init_nodb_doc,
|
|
"nss_init_nodb()\n\
|
|
\n\
|
|
Performs tasks required to run Network Security Services without setting up\n\
|
|
configuration files. Important: This NSS function is not intended for use with\n\
|
|
SSL, which requires that the certificate and key database files be opened.\n\
|
|
\n\
|
|
nss_init_nodb opens only the temporary database and the internal PKCS #112\n\
|
|
module. Unlike nss_init, nss_init_nodb allows applications that do not have\n\
|
|
access to storage for databases to run raw crypto, hashing, and certificate\n\
|
|
functions. nss_init_nodb is not idempotent, so call it only once. The policy\n\
|
|
flags for all cipher suites are turned off by default, disallowing all cipher\n\
|
|
suites. Therefore, an application cannot use NSS to perform any cryptographic\n\
|
|
operations until after it enables appropriate cipher suites by calling one of\n\
|
|
the SSL Export Policy Functions.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_init_nodb(PyObject *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (NSS_NoDB_Init(NULL) != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_initialize_doc,
|
|
"nss_initialize(cert_dir=None, cert_prefix=None, key_prefix=None, secmod_name=None, flags=0)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cert_dir : string\n\
|
|
Pathname of the directory where the certificate, key, and\n\
|
|
security module databases reside.\n\
|
|
\n\
|
|
cert_prefix : string\n\
|
|
Prefix added to the beginning of the certificate database,\n\
|
|
for example,\"https-server1-\".\n\
|
|
\n\
|
|
key_prefix : string\n\
|
|
Prefix added to the beginning of the key database,\n\
|
|
for example, \"https-server1-\".\n\
|
|
\n\
|
|
secmod_name : string\n\
|
|
Name of the security module database,\n\
|
|
usually \"secmod.db\".\n\
|
|
\n\
|
|
flags\n\
|
|
Bit flags that specify how NSS should be initialized.\n\
|
|
\n\
|
|
`nss_initialize()` initializes NSS. It is more flexible than `nss_init()`,\n\
|
|
`nss_init_read_write()`, and `nss_init_nodb()`. If any of those simpler NSS\n\
|
|
initialization functions suffices for your needs, call that instead.\n\
|
|
\n\
|
|
By default `nss_initialize()` and `nss_init_context()` open the\n\
|
|
internal PK11 slot (see `get_internal_slot()`) in Read Write (RW) mode\n\
|
|
as opposed to `nss_init()` which opens it in Read Only (RO) mode. If\n\
|
|
you want RO mode you pass the `NSS_INIT_READONLY` flag.\n\
|
|
\n\
|
|
The flags parameter is a bitwise OR of the following flags:\n\
|
|
\n\
|
|
NSS_INIT_READONLY\n\
|
|
Open the databases read only.\n\
|
|
\n\
|
|
NSS_INIT_NOCERTDB\n\
|
|
Don't open the cert DB and key DB's, just initialize the volatile\n\
|
|
certdb.\n\
|
|
\n\
|
|
NSS_INIT_NOMODDB\n\
|
|
Don't open the security module DB, just initialize the PKCS #11 module.\n\
|
|
\n\
|
|
NSS_INIT_FORCEOPEN\n\
|
|
Continue to force initializations even if the databases cannot be\n\
|
|
opened.\n\
|
|
\n\
|
|
NSS_INIT_NOROOTINIT\n\
|
|
Don't try to look for the root certs module automatically.\n\
|
|
\n\
|
|
NSS_INIT_OPTIMIZESPACE\n\
|
|
Optimize for space instead of speed. Use smaller tables and caches.\n\
|
|
\n\
|
|
NSS_INIT_PK11THREADSAFE\n\
|
|
Only load PKCS#11 modules that are thread-safe, i.e., that support\n\
|
|
locking - either OS locking or NSS-provided locks . If a PKCS#11 module\n\
|
|
isn't thread-safe, don't serialize its calls; just don't load it\n\
|
|
instead. This is necessary if another piece of code is using the same\n\
|
|
PKCS#11 modules that NSS is accessing without going through NSS, for\n\
|
|
example, the Java SunPKCS11 provider.\n\
|
|
\n\
|
|
NSS_INIT_PK11RELOAD\n\
|
|
Ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED error when loading PKCS#11\n\
|
|
modules. This is necessary if another piece of code is using the same\n\
|
|
PKCS#11 modules that NSS is accessing without going through NSS, for\n\
|
|
example, Java SunPKCS11 provider.\n\
|
|
\n\
|
|
NSS_INIT_NOPK11FINALIZE\n\
|
|
Never call C_Finalize on any PKCS#11 module. This may be necessary in\n\
|
|
order to ensure continuous operation and proper shutdown sequence if\n\
|
|
another piece of code is using the same PKCS#11 modules that NSS is\n\
|
|
accessing without going through NSS, for example, Java SunPKCS11\n\
|
|
provider. The following limitation applies when this is set :\n\
|
|
SECMOD_WaitForAnyTokenEvent will not use C_WaitForSlotEvent, in order\n\
|
|
to prevent the need for C_Finalize. This call will be emulated instead.\n\
|
|
\n\
|
|
NSS_INIT_RESERVED\n\
|
|
Currently has no effect, but may be used in the future to trigger\n\
|
|
better cooperation between PKCS#11 modules used by both NSS and the\n\
|
|
Java SunPKCS11 provider. This should occur after a new flag is defined\n\
|
|
for C_Initialize by the PKCS#11 working group.\n\
|
|
\n\
|
|
NSS_INIT_COOPERATE\n\
|
|
Sets the above four recommended options for applications that use both\n\
|
|
NSS and the Java SunPKCS11 provider.\n\
|
|
\n\
|
|
Hint: You can obtain a printable representation of the flags via `nss_init_flags`.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_initialize(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"cert_dir", "cert_prefix", "key_prefix", "secmod_name", "flags", NULL};
|
|
char *cert_dir = NULL;
|
|
char *cert_prefix = NULL;
|
|
char *key_prefix = NULL;
|
|
char *secmod_name = NULL;
|
|
unsigned long flags = 0;
|
|
SECStatus status;
|
|
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|esesesesk:nss_initialize", kwlist,
|
|
"utf-8", &cert_dir,
|
|
"utf-8", &cert_prefix,
|
|
"utf-8", &key_prefix,
|
|
"utf-8", &secmod_name,
|
|
&flags))
|
|
return NULL;
|
|
|
|
if ((status = NSS_Initialize(cert_dir, cert_prefix, key_prefix, secmod_name, flags)) != SECSuccess) {
|
|
set_nspr_error(NULL);
|
|
}
|
|
|
|
if (cert_dir) PyMem_Free(cert_dir);
|
|
if (cert_prefix) PyMem_Free(cert_prefix);
|
|
if (key_prefix) PyMem_Free(key_prefix);
|
|
if (secmod_name) PyMem_Free(secmod_name);
|
|
|
|
if (status == SECSuccess) {
|
|
Py_RETURN_NONE;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_init_context_doc,
|
|
"nss_init_context(cert_dir=None, cert_prefix=None, key_prefix=None, secmod_name=None, init_params=None, flags=0) -> `InitContext`\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cert_dir : string\n\
|
|
Pathname of the directory where the certificate, key, and\n\
|
|
security module databases reside.\n\
|
|
\n\
|
|
cert_prefix : string\n\
|
|
Prefix added to the beginning of the certificate database,\n\
|
|
for example,\"https-server1-\".\n\
|
|
\n\
|
|
key_prefix : string\n\
|
|
Prefix added to the beginning of the key database,\n\
|
|
for example, \"https-server1-\".\n\
|
|
\n\
|
|
secmod_name : string\n\
|
|
Name of the security module database,\n\
|
|
usually \"secmod.db\".\n\
|
|
\n\
|
|
init_params : `InitContext` object\n\
|
|
Object with a set of initialization parameters.\n\
|
|
See `InitContext`.\n\
|
|
\n\
|
|
flags\n\
|
|
Bit flags that specify how NSS should be initialized.\n\
|
|
\n\
|
|
`nss_init_context()` initializes NSS within a context and returns a\n\
|
|
`InitContext` object. Contexts are used when multiple entities within\n\
|
|
a single process wish to use NSS without colliding such as\n\
|
|
libraries.\n\
|
|
\n\
|
|
By default `nss_initialize()` and `nss_init_context()` open the\n\
|
|
internal PK11 slot (see `get_internal_slot()`) in Read Write (RW) mode\n\
|
|
as opposed to `nss_init()` which opens it in Read Only (RO) mode. If\n\
|
|
you want RO mode you pass the `NSS_INIT_READONLY` flag.\n\
|
|
\n\
|
|
The flags parameter is a bitwise OR of the following flags:\n\
|
|
\n\
|
|
NSS_INIT_READONLY\n\
|
|
Open the databases read only.\n\
|
|
\n\
|
|
NSS_INIT_NOCERTDB\n\
|
|
Don't open the cert DB and key DB's, just initialize the volatile\n\
|
|
certdb.\n\
|
|
\n\
|
|
NSS_INIT_NOMODDB\n\
|
|
Don't open the security module DB, just initialize the PKCS #11 module.\n\
|
|
\n\
|
|
NSS_INIT_FORCEOPEN\n\
|
|
Continue to force initializations even if the databases cannot be\n\
|
|
opened.\n\
|
|
\n\
|
|
NSS_INIT_NOROOTINIT\n\
|
|
Don't try to look for the root certs module automatically.\n\
|
|
\n\
|
|
NSS_INIT_OPTIMIZESPACE\n\
|
|
Optimize for space instead of speed. Use smaller tables and caches.\n\
|
|
\n\
|
|
NSS_INIT_PK11THREADSAFE\n\
|
|
Only load PKCS#11 modules that are thread-safe, i.e., that support\n\
|
|
locking - either OS locking or NSS-provided locks . If a PKCS#11 module\n\
|
|
isn't thread-safe, don't serialize its calls; just don't load it\n\
|
|
instead. This is necessary if another piece of code is using the same\n\
|
|
PKCS#11 modules that NSS is accessing without going through NSS, for\n\
|
|
example, the Java SunPKCS11 provider.\n\
|
|
\n\
|
|
NSS_INIT_PK11RELOAD\n\
|
|
Ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED error when loading PKCS#11\n\
|
|
modules. This is necessary if another piece of code is using the same\n\
|
|
PKCS#11 modules that NSS is accessing without going through NSS, for\n\
|
|
example, Java SunPKCS11 provider.\n\
|
|
\n\
|
|
NSS_INIT_NOPK11FINALIZE\n\
|
|
Never call C_Finalize on any PKCS#11 module. This may be necessary in\n\
|
|
order to ensure continuous operation and proper shutdown sequence if\n\
|
|
another piece of code is using the same PKCS#11 modules that NSS is\n\
|
|
accessing without going through NSS, for example, Java SunPKCS11\n\
|
|
provider. The following limitation applies when this is set :\n\
|
|
SECMOD_WaitForAnyTokenEvent will not use C_WaitForSlotEvent, in order\n\
|
|
to prevent the need for C_Finalize. This call will be emulated instead.\n\
|
|
\n\
|
|
NSS_INIT_RESERVED\n\
|
|
Currently has no effect, but may be used in the future to trigger\n\
|
|
better cooperation between PKCS#11 modules used by both NSS and the\n\
|
|
Java SunPKCS11 provider. This should occur after a new flag is defined\n\
|
|
for C_Initialize by the PKCS#11 working group.\n\
|
|
\n\
|
|
NSS_INIT_COOPERATE\n\
|
|
Sets the above four recommended options for applications that use both\n\
|
|
NSS and the Java SunPKCS11 provider.\n\
|
|
\n\
|
|
Hint: You can obtain a printable representation of the flags via `nss_init_flags`.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_init_context(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"cert_dir", "cert_prefix", "key_prefix",
|
|
"secmod_name", "init_params", "flags", NULL};
|
|
char *cert_dir = NULL;
|
|
char *cert_prefix = NULL;
|
|
char *key_prefix = NULL;
|
|
char *secmod_name = NULL;
|
|
InitParameters *py_init_params = NULL;
|
|
unsigned long flags = 0;
|
|
NSSInitContext *init_context = NULL;
|
|
PyObject *py_init_context = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|esesesesO!k:nss_init_context", kwlist,
|
|
"utf-8", &cert_dir,
|
|
"utf-8", &cert_prefix,
|
|
"utf-8", &key_prefix,
|
|
"utf-8", &secmod_name,
|
|
&InitParametersType, &py_init_params,
|
|
&flags))
|
|
return NULL;
|
|
|
|
if ((init_context = NSS_InitContext(cert_dir, cert_prefix, key_prefix, secmod_name,
|
|
py_init_params ? &py_init_params->params : NULL,
|
|
flags)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((py_init_context = InitContext_new_from_NSSInitContext(init_context)) == NULL) {
|
|
NSS_ShutdownContext(init_context);
|
|
init_context = NULL;
|
|
}
|
|
|
|
if (cert_dir) PyMem_Free(cert_dir);
|
|
if (cert_prefix) PyMem_Free(cert_prefix);
|
|
if (key_prefix) PyMem_Free(key_prefix);
|
|
if (secmod_name) PyMem_Free(secmod_name);
|
|
|
|
if (init_context != NULL) {
|
|
return py_init_context;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_shutdown_context_doc,
|
|
"nss_shutdown_context(context) -> \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
context : `InitContext` object\n\
|
|
A `InitContext` returned from a previous\n\
|
|
call to `nss_init_context`.\n\
|
|
\n\
|
|
xxx\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_shutdown_context(PyObject *self, PyObject *args)
|
|
{
|
|
InitContext *py_context = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O!:nss_shutdown_context",
|
|
&InitContextType, &py_context))
|
|
return NULL;
|
|
|
|
if (NSS_ShutdownContext(py_context->context) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_shutdown_doc,
|
|
"nss_shutdown()\n\
|
|
\n\
|
|
Closes the key and certificate databases that were opened by nss_init().\n\
|
|
\n\
|
|
NSS can only shutdown successfully if all NSS objects have been\n\
|
|
released, otherwise nss_shutdown will fail with the error code\n\
|
|
SEC_ERROR_BUSY. Here are some tips to make sure nss_shutdown will\n\
|
|
succeed. [1]_\n\
|
|
\n\
|
|
* If the process is a SSL client make sure you call\n\
|
|
`ssl.clear_session_cache`.\n\
|
|
\n\
|
|
* If the process is a SSL server make sure you call\n\
|
|
`ssl.shutdown_server_session_id_cache()`.\n\
|
|
\n\
|
|
* Make sure all sockets have been closed, open SSL sockets hold\n\
|
|
references NSS objects.\n\
|
|
\n\
|
|
* Explicitly delete Python objects which contain NSS objects using the\n\
|
|
del command. [2]_\n\
|
|
\n\
|
|
* Use `nss.dump_certificate_cache_info()` to provide information about\n\
|
|
which cached objects may still persist and be responsible for\n\
|
|
preventing a full NSS shutdown.\n\
|
|
\n\
|
|
.. [1] If the leaked objects are subsequently released after\n\
|
|
nss_shutdown is called NSS can be reinitialized with the\n\
|
|
various NSS initialization routines. In this cass teh\n\
|
|
SEC_ERROR_BUSY error can be thought of as an informatiive\n\
|
|
warning.\n\
|
|
\n\
|
|
.. [2] This Python binding to NSS wraps each NSS object inside a\n\
|
|
Python object. Like NSS objects Python objects are reference\n\
|
|
counted. When the last reference to the Python object\n\
|
|
disappears the Python object is destroyed. The destructor for a\n\
|
|
Python object wrapping an NSS object releases the NSS reference\n\
|
|
to the NSS object. Thus if any Python objects which wrap NSS\n\
|
|
objects remain \"live\" nss_shutdown will fail. Python objects\n\
|
|
are typically released by the Python interpretor when the\n\
|
|
variable holding the object is assigned a new object or when\n\
|
|
the variable holding the object goes out of scope. This means\n\
|
|
you may need to manually delete some objects using the del\n\
|
|
command rather relying on Python's automatic garbage\n\
|
|
collection. Consider this example:\n\
|
|
\n\
|
|
def foo():\n\
|
|
nss.nss_init(certdir)\n\
|
|
sock = ssl.SSLSocket()\n\
|
|
nss.nss_shutdown()\n\
|
|
\n\
|
|
When nss_shutown() is called the sock object is still alive and\n\
|
|
holds references to NSS objects. The sock object won't be\n\
|
|
released by Python until it goes out of scope when the function\n\
|
|
exits. Thus the shutdown will fail with SEC_ERROR_BUSY. But you\n\
|
|
can explicitly force the sock object to be released by\n\
|
|
explictily deleting it, for example:\n\
|
|
\n\
|
|
def foo():\n\
|
|
nss.nss_init(certdir)\n\
|
|
sock = ssl.SSLSocket()\n\
|
|
del sock\n\
|
|
nss.nss_shutdown()\n\
|
|
\n\
|
|
Another way to avoid this issue is to arrange your code such\n\
|
|
that nss_shutdown is called from a location in your code which\n\
|
|
is not in scope for any NSS objects created. This also implies\n\
|
|
you shouldn't assign NSS objects to globals.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_shutdown(PyObject *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if (NSS_Shutdown() != SECSuccess) {
|
|
Py_BLOCK_THREADS
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_dump_certificate_cache_info_doc,
|
|
"dump_certificate_cache_info()\n\
|
|
\n\
|
|
Dump the contents of the certificate cache and the temporary\n\
|
|
cert store to stdout.\n\
|
|
\n\
|
|
Use this as a debugging aid to detect leaked references of certs at\n\
|
|
shutdown time. For example if `nss.nss_shutdown()` throws a\n\
|
|
SEC_ERROR_BUSY exception.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_dump_certificate_cache_info(PyObject *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
nss_DumpCertificateCacheInfo();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_oid_str_doc,
|
|
"oid_str(oid) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
oid : may be one of integer, string, SecItem\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* integer:: A SEC OID enumeration constant, also known as a tag\n\
|
|
(i.e. SEC_OID_*) for example SEC_OID_AVA_COMMON_NAME.\n\
|
|
* string:: A string in dotted decimal representation, for example\n\
|
|
'OID.2.5.4.3'. The 'OID.' prefix is optional.\n\
|
|
Or a string for the tag name (e.g. 'SEC_OID_AVA_COMMON_NAME')\n\
|
|
The 'SEC_OID\\_' prefix is optional. Or one of the canonical\n\
|
|
abbreviations (e.g. 'cn'). Case is not significant.\n\
|
|
* SecItem:: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
\n\
|
|
Given an oid return it's description as a string.\n\
|
|
");
|
|
static PyObject *
|
|
cert_oid_str(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *arg;
|
|
int oid_tag;
|
|
SECOidData *oiddata;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:oid_str", &arg))
|
|
return NULL;
|
|
|
|
oid_tag = get_oid_tag_from_object(arg);
|
|
if (oid_tag == SEC_OID_UNKNOWN || oid_tag == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((oiddata = SECOID_FindOIDByTag(oid_tag)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return PyString_FromString(oiddata->desc);
|
|
}
|
|
|
|
|
|
PyDoc_STRVAR(cert_oid_tag_name_doc,
|
|
"oid_tag_name(oid) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
oid : may be one of integer, string, SecItem\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* integer:: A SEC OID enumeration constant, also known as a tag\n\
|
|
(i.e. SEC_OID_*) for example SEC_OID_AVA_COMMON_NAME.\n\
|
|
* string:: A string in dotted decimal representation, for example\n\
|
|
'OID.2.5.4.3'. The 'OID.' prefix is optional.\n\
|
|
Or a string for the tag name (e.g. 'SEC_OID_AVA_COMMON_NAME')\n\
|
|
The 'SEC_OID\\_' prefix is optional. Or one of the canonical\n\
|
|
abbreviations (e.g. 'cn'). Case is not significant.\n\
|
|
* SecItem:: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
\n\
|
|
Given an oid return it's tag constant as a string.\n\
|
|
");
|
|
static PyObject *
|
|
cert_oid_tag_name(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *arg;
|
|
int oid_tag;
|
|
PyObject *py_name;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:oid_tag_name", &arg))
|
|
return NULL;
|
|
|
|
oid_tag = get_oid_tag_from_object(arg);
|
|
if (oid_tag == SEC_OID_UNKNOWN || oid_tag == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
py_name = oid_tag_name_from_tag(oid_tag);
|
|
return py_name;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_oid_tag_doc,
|
|
"oid_tag(oid) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
oid : may be one of integer, string, SecItem\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* integer:: A SEC OID enumeration constant, also known as a tag\n\
|
|
(i.e. SEC_OID_*) for example SEC_OID_AVA_COMMON_NAME.\n\
|
|
* string:: A string in dotted decimal representation, for example\n\
|
|
'OID.2.5.4.3'. The 'OID.' prefix is optional.\n\
|
|
Or a string for the tag name (e.g. 'SEC_OID_AVA_COMMON_NAME')\n\
|
|
The 'SEC_OID\\_' prefix is optional. Or one of the canonical\n\
|
|
abbreviations (e.g. 'cn'). Case is not significant.\n\
|
|
* SecItem:: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
\n\
|
|
Given an oid return it's tag constant.\n\
|
|
");
|
|
static PyObject *
|
|
cert_oid_tag(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *result;
|
|
PyObject *arg;
|
|
int oid_tag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:oid_tag", &arg))
|
|
return NULL;
|
|
|
|
oid_tag = get_oid_tag_from_object(arg);
|
|
if (oid_tag == SEC_OID_UNKNOWN || oid_tag == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
result = PyInt_FromLong(oid_tag);
|
|
return result;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_oid_dotted_decimal_doc,
|
|
"oid_dotted_decimal(oid) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
oid : may be one of integer, string, SecItem\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* integer:: A SEC OID enumeration constant, also known as a tag\n\
|
|
(i.e. SEC_OID_*) for example SEC_OID_AVA_COMMON_NAME.\n\
|
|
* string:: A string in dotted decimal representation, for example\n\
|
|
'OID.2.5.4.3'. The 'OID.' prefix is optional.\n\
|
|
Or a string for the tag name (e.g. 'SEC_OID_AVA_COMMON_NAME')\n\
|
|
The 'SEC_OID\\_' prefix is optional. Or one of the canonical\n\
|
|
abbreviations (e.g. 'cn'). Case is not significant.\n\
|
|
* SecItem:: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
\n\
|
|
Given an oid return it's tag constant as a string.\n\
|
|
");
|
|
static PyObject *
|
|
cert_oid_dotted_decimal(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *arg;
|
|
int oid_tag;
|
|
SECOidData *oiddata;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O:oid_dotted_decimal", &arg))
|
|
return NULL;
|
|
|
|
oid_tag = get_oid_tag_from_object(arg);
|
|
if (oid_tag == SEC_OID_UNKNOWN || oid_tag == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((oiddata = SECOID_FindOIDByTag(oid_tag)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return oid_secitem_to_pystr_dotted_decimal(&oiddata->oid);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
key_mechanism_type_to_pystr(CK_MECHANISM_TYPE mechanism)
|
|
{
|
|
PyObject *py_value;
|
|
PyObject *py_name;
|
|
|
|
if ((py_value = PyInt_FromLong(mechanism)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_name = PyDict_GetItem(ckm_value_to_name, py_value)) == NULL) {
|
|
Py_DECREF(py_value);
|
|
PyErr_Format(PyExc_KeyError, "mechanism name not found: %lu", mechanism);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_value);
|
|
Py_INCREF(py_name);
|
|
|
|
return py_name;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_key_mechanism_type_name_doc,
|
|
"key_mechanism_type_name(mechanism) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Given a key mechanism enumeration constant (CKM_*)\n\
|
|
return it's name as a string\n\
|
|
");
|
|
static PyObject *
|
|
pk11_key_mechanism_type_name(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:key_mechanism_type_name", &mechanism))
|
|
return NULL;
|
|
|
|
return key_mechanism_type_to_pystr(mechanism);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_key_mechanism_type_from_name_doc,
|
|
"key_mechanism_type_from_name(name) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
name of key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Given the name of a key mechanism enumeration constant (CKM_*)\n\
|
|
return it's integer constant\n\
|
|
The string comparison is case insensitive and will match with\n\
|
|
or without the CKM\\_ prefix\n\
|
|
");
|
|
static PyObject *
|
|
pk11_key_mechanism_type_from_name(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *py_name;
|
|
PyObject *py_lower_name;
|
|
PyObject *py_value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "S:key_mechanism_type_from_name", &py_name))
|
|
return NULL;
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_value = PyDict_GetItem(ckm_name_to_value, py_lower_name)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "mechanism name not found: %s", PyString_AsString(py_name));
|
|
Py_DECREF(py_lower_name);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_lower_name);
|
|
Py_INCREF(py_value);
|
|
|
|
return py_value;
|
|
}
|
|
|
|
static PyObject *
|
|
pk11_attribute_type_to_pystr(CK_ATTRIBUTE_TYPE type)
|
|
{
|
|
PyObject *py_value;
|
|
PyObject *py_name;
|
|
|
|
if ((py_value = PyInt_FromLong(type)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_name = PyDict_GetItem(cka_value_to_name, py_value)) == NULL) {
|
|
Py_DECREF(py_value);
|
|
PyErr_Format(PyExc_KeyError, "attribute type name not found: %lu", type);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_value);
|
|
Py_INCREF(py_name);
|
|
|
|
return py_name;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_attribute_type_name_doc,
|
|
"pk11_attribute_type_name(type) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
type : int\n\
|
|
PK11 attribute type constant (CKA_*)\n\
|
|
\n\
|
|
Given a PK11 attribute type constant (CKA_*)\n\
|
|
return it's name as a string\n\
|
|
");
|
|
static PyObject *
|
|
pk11_pk11_attribute_type_name(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long type;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:pk11_attribute_type_name", &type))
|
|
return NULL;
|
|
|
|
return pk11_attribute_type_to_pystr(type);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_pk11_attribute_type_from_name_doc,
|
|
"pk11_attribute_type_from_name(name) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
name of PK11 attribute type constant (CKA_*)\n\
|
|
\n\
|
|
Given the name of a PK11 attribute type constant (CKA_*)\n\
|
|
return it's integer constant\n\
|
|
The string comparison is case insensitive and will match with\n\
|
|
or without the CKA\\_ prefix\n\
|
|
");
|
|
static PyObject *
|
|
pk11_pk11_attribute_type_from_name(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *py_name;
|
|
PyObject *py_lower_name;
|
|
PyObject *py_value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "S:pk11_attribute_type_from_name", &py_name))
|
|
return NULL;
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_value = PyDict_GetItem(cka_name_to_value, py_lower_name)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "attribute name not found: %s", PyString_AsString(py_name));
|
|
Py_DECREF(py_lower_name);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_lower_name);
|
|
Py_INCREF(py_value);
|
|
|
|
return py_value;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_disabled_reason_str_doc,
|
|
"pk11_disabled_reason_str(reason) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
reason : int\n\
|
|
PK11 slot disabled reason constant (PK11_DIS_*)\n\
|
|
\n\
|
|
Given a PK11 slot disabled reason constant (PK11_DIS_*)\n\
|
|
return a descriptive string\n\
|
|
");
|
|
static PyObject *
|
|
pk11_pk11_disabled_reason_str(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long reason;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:pk11_disabled_reason_str", &reason))
|
|
return NULL;
|
|
|
|
return PyString_FromString(pk11_disabled_reason_str(reason));
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_disabled_reason_name_doc,
|
|
"pk11_disabled_reason_name(reason) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
reason : int\n\
|
|
PK11 slot disabled reason constant (PK11_DIS_*)\n\
|
|
\n\
|
|
Given a PK11 slot disabled reason constant (PK11_DIS_*)\n\
|
|
return the constant as a string.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_pk11_disabled_reason_name(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long reason;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:pk11_disabled_reason_name", &reason))
|
|
return NULL;
|
|
|
|
return PyString_FromString(pk11_disabled_reason_name(reason));
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_pk11_logout_all_doc,
|
|
"pk11_logout_all()\n\
|
|
\n\
|
|
Logout of every slot for all modules.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_pk11_logout_all(PK11Slot *self, PyObject *args)
|
|
{
|
|
TraceMethodEnter(self);
|
|
|
|
PK11_LogoutAll();
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_get_best_slot_doc,
|
|
"get_best_slot(mechanism, [user_data1, ...]) -> PK11Slot\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Find the best slot which supports the given mechanism.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_get_best_slot(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 1;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
unsigned long mechanism;
|
|
PK11SlotInfo *slot = NULL;
|
|
PyObject *py_slot = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
if (!PyArg_ParseTuple(parse_args, "k:get_best_slot", &mechanism)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((slot = PK11_GetBestSlot(mechanism, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
if ((py_slot = PK11Slot_new_from_PK11SlotInfo(slot)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Slot object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_slot;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_get_internal_slot_doc,
|
|
"get_internal_slot() -> PK11Slot\n\
|
|
\n\
|
|
Get the default internal slot.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_get_internal_slot(PyObject *self, PyObject *args)
|
|
{
|
|
PK11SlotInfo *slot = NULL;
|
|
PyObject *py_slot = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((slot = PK11_GetInternalSlot()) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((py_slot = PK11Slot_new_from_PK11SlotInfo(slot)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Slot object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_slot;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_get_internal_key_slot_doc,
|
|
"get_internal_key_slot() -> PK11Slot\n\
|
|
\n\
|
|
Get the default internal key slot.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_get_internal_key_slot(PyObject *self, PyObject *args)
|
|
{
|
|
PK11SlotInfo *slot = NULL;
|
|
PyObject *py_slot = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if ((slot = PK11_GetInternalKeySlot()) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((py_slot = PK11Slot_new_from_PK11SlotInfo(slot)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Slot object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_slot;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_find_slot_by_name_doc,
|
|
"find_slot_by_name(name) -> `PK11Slot`\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
slot name\n\
|
|
\n\
|
|
Given a slot name return a `PK11Slot` object.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pk11_find_slot_by_name(PyObject *self, PyObject *args)
|
|
{
|
|
char *slot_name = NULL;
|
|
PK11SlotInfo *slot = NULL;
|
|
PyObject *py_slot = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "es:find_slot_by_name",
|
|
"utf-8", &slot_name))
|
|
return NULL;
|
|
|
|
if ((slot = PK11_FindSlotByName(slot_name)) == NULL) {
|
|
PyMem_Free(slot_name);
|
|
return set_nspr_error("could not find slot name \"%s\"", slot_name);
|
|
}
|
|
PyMem_Free(slot_name);
|
|
|
|
if ((py_slot = PK11Slot_new_from_PK11SlotInfo(slot)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Slot object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_slot;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_create_context_by_sym_key_doc,
|
|
"create_context_by_sym_key(mechanism, operation, sym_key, sec_param=None) -> PK11Context\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
operation : int\n\
|
|
type of operation this context will be doing. A (CKA_*) constant\n\
|
|
(e.g. CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, CKA_VERIFY, CKA_DIGEST)\n\
|
|
sym_key : PK11SymKey object\n\
|
|
symmetric key\n\
|
|
sec_param : SecItem object or None\n\
|
|
mechanism parameters used to build this context or None.\n\
|
|
\n\
|
|
Create a context from a symmetric key)\n\
|
|
");
|
|
static PyObject *
|
|
pk11_create_context_by_sym_key(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"mechanism", "operation", "sym_key", "sec_param", NULL};
|
|
unsigned long mechanism;
|
|
unsigned long operation;
|
|
PyPK11SymKey *py_sym_key;
|
|
SecItem *py_sec_param;
|
|
PK11Context *pk11_context;
|
|
PyObject *py_pk11_context;
|
|
SECItem null_param = {0};
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "kkO!|O&:create_context_by_sym_key", kwlist,
|
|
&mechanism, &operation,
|
|
&PK11SymKeyType, &py_sym_key,
|
|
SecItemOrNoneConvert, &py_sec_param))
|
|
return NULL;
|
|
|
|
if ((pk11_context =
|
|
PK11_CreateContextBySymKey(mechanism, operation, py_sym_key->pk11_sym_key,
|
|
py_sec_param ? &py_sec_param->item : &null_param)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((py_pk11_context = PyPK11Context_new_from_PK11Context(pk11_context)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Context object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_pk11_context;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_import_sym_key_doc,
|
|
"import_sym_key(slot, mechanism, origin, operation, key_data, [user_data1, ...]) -> PK11SymKey\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
slot : PK11Slot object\n\
|
|
designated PK11 slot\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
origin : int\n\
|
|
PK11 origin enumeration (PK11Origin*)\n\
|
|
e.g. PK11_OriginDerive, PK11_OriginUnwrap, etc.\n\
|
|
operation : int\n\
|
|
type of operation this context will be doing. A (CKA_*) constant\n\
|
|
(e.g. CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, CKA_VERIFY, CKA_DIGEST)\n\
|
|
key_data: SecItem object\n\
|
|
key data encapsulated in a SECItem used to build the symmetric key.\n\
|
|
user_dataN : object ...\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
Create a PK11SymKey from data)\n\
|
|
");
|
|
static PyObject *
|
|
pk11_import_sym_key(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 5;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
PK11Slot *py_slot;
|
|
unsigned long mechanism;
|
|
unsigned long origin;
|
|
unsigned long operation;
|
|
SecItem *py_key_data;
|
|
PK11SymKey *sym_key;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
|
|
if (!PyArg_ParseTuple(parse_args, "O!kkkO!:import_sym_key",
|
|
&PK11SlotType, &py_slot,
|
|
&mechanism, &origin, &operation,
|
|
&SecItemType, &py_key_data)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((sym_key = PK11_ImportSymKey(py_slot->slot, mechanism, origin, operation,
|
|
&py_key_data->item, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
return PyPK11SymKey_new_from_PK11SymKey(sym_key);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_pub_wrap_sym_key_doc,
|
|
"pub_wrap_sym_key(mechanism, pub_key, sym_key) -> SecItem\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
CK_MECHANISM_TYPE enumerated constant\n\
|
|
pub_key : `PublicKey` object\n\
|
|
Public key used to wrap.\n\
|
|
sym_key : `PK11SymKey` object\n\
|
|
Symmetric key that will be wrapped.\n\
|
|
:returns:\n\
|
|
Wrapped symmetric key as SecItem\n\
|
|
\n\
|
|
Wraps a public key wrap (which only RSA can do).\n\
|
|
");
|
|
static PyObject *
|
|
pk11_pub_wrap_sym_key(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
PublicKey *py_pub_key = NULL;
|
|
PyPK11SymKey *py_sym_key = NULL;
|
|
size_t key_len = 0;
|
|
SecItem *py_wrapped_key = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "kO!O!:pub_wrap_sym_key",
|
|
&mechanism,
|
|
&PublicKeyType, &py_pub_key,
|
|
&PK11SymKeyType, &py_sym_key))
|
|
return NULL;
|
|
|
|
key_len = SECKEY_PublicKeyStrength(py_pub_key->pk);
|
|
if ((py_wrapped_key = (SecItem *)SecItem_new_alloc(key_len, siBuffer, SECITEM_wrapped_key)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((PK11_PubWrapSymKey(mechanism, py_pub_key->pk, py_sym_key->pk11_sym_key,
|
|
&py_wrapped_key->item) != SECSuccess)) {
|
|
Py_BLOCK_THREADS
|
|
Py_CLEAR(py_wrapped_key);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
return (PyObject *)py_wrapped_key;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_create_digest_context_doc,
|
|
"create_digest_context(hash_alg) -> PK11Context\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
hash_alg : int\n\
|
|
hash algorithm enumeration (SEC_OID_*)\n\
|
|
e.g.: SEC_OID_MD5, SEC_OID_SHA1, SEC_OID_SHA256, SEC_OID_SHA512, etc.\n\
|
|
\n\
|
|
Create a context for performing digest (hash) operations)\n\
|
|
");
|
|
static PyObject *
|
|
pk11_create_digest_context(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long hash_alg;
|
|
PK11Context *pk11_context;
|
|
PyObject *py_pk11_context;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:create_digest_context", &hash_alg))
|
|
return NULL;
|
|
|
|
if ((pk11_context = PK11_CreateDigestContext(hash_alg)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((py_pk11_context =
|
|
PyPK11Context_new_from_PK11Context(pk11_context)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create PK11Context object");
|
|
return NULL;
|
|
}
|
|
|
|
return py_pk11_context;
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_param_from_iv_doc,
|
|
"param_from_iv(mechanism, iv=None) -> SecItem\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
iv : SecItem object\n\
|
|
initialization vector. If there is no initialization vector you may also pass\n\
|
|
None or an empty SecItem object (e.g. SecItem())\n\
|
|
\n\
|
|
Return a SecItem to be used as the initialization vector for encryption/decryption.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_param_from_iv(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"mechanism", "iv", NULL};
|
|
unsigned long mechanism;
|
|
SecItem *py_iv;
|
|
SECItem *sec_param;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|O&:param_from_iv", kwlist,
|
|
&mechanism, SecItemOrNoneConvert, &py_iv))
|
|
return NULL;
|
|
|
|
if ((sec_param = PK11_ParamFromIV(mechanism, py_iv ? &py_iv->item : NULL)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return SecItem_new_from_SECItem(sec_param, SECITEM_iv_param);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_param_from_algid_doc,
|
|
"param_from_algid(algid) -> SecItem\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
algid : AlgorithmID object\n\
|
|
algorithm id\n\
|
|
\n\
|
|
Return a SecItem containing a encryption param derived from a AlgorithmID.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_param_from_algid(PyObject *self, PyObject *args)
|
|
{
|
|
AlgorithmID *py_algorithm;
|
|
SECItem *param;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "O!:param_from_algid", &AlgorithmIDType, &py_algorithm))
|
|
return NULL;
|
|
|
|
if ((param = PK11_ParamFromAlgid(&py_algorithm->id)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return SecItem_new_from_SECItem(param, SECITEM_unknown);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_generate_new_param_doc,
|
|
"generate_new_param(mechanism, sym_key=None) -> SecItem\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
sym_key : PK11SymKey object or None\n\
|
|
symmetric key or None\n\
|
|
\n\
|
|
Return a SecItem containing a encryption param.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_generate_new_param(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"mechanism", "sym_key", NULL};
|
|
unsigned long mechanism;
|
|
PyPK11SymKey *py_sym_key;
|
|
SECItem *param;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|O&:generate_new_param", kwlist,
|
|
&mechanism, SymKeyOrNoneConvert, &py_sym_key))
|
|
return NULL;
|
|
|
|
if ((param = PK11_GenerateNewParam(mechanism,
|
|
py_sym_key ? py_sym_key->pk11_sym_key : NULL)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return SecItem_new_from_SECItem(param, SECITEM_unknown);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_algtag_to_mechanism_doc,
|
|
"algtag_to_mechanism(algtag) -> mechanism\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
algtag : int\n\
|
|
algorithm tag (e.g. SEC_OID_*)\n\
|
|
\n\
|
|
Returns the key mechanism enumeration constant (CKM_*)\n\
|
|
given an algorithm tag. Throws a KeyError exception if the \n\
|
|
algorithm tag is invalid.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_algtag_to_mechanism(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long algtag;
|
|
unsigned long mechanism;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:algtag_to_mechanism", &algtag))
|
|
return NULL;
|
|
|
|
if ((mechanism = PK11_AlgtagToMechanism(algtag)) == CKM_INVALID_MECHANISM) {
|
|
PyErr_Format(PyExc_KeyError, "algtag not found: %#lx", algtag);
|
|
return NULL;
|
|
}
|
|
|
|
return PyInt_FromLong(mechanism);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_mechanism_to_algtag_doc,
|
|
"mechanism_to_algtag(mechanism) -> algtag\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Returns the algtag given key mechanism enumeration constant (CKM_*)\n\
|
|
Throws an KeyError exception if the mechanism is invalid.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_mechanism_to_algtag(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long algtag;
|
|
unsigned long mechanism;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:mechanism_to_algtag", &mechanism))
|
|
return NULL;
|
|
|
|
if ((algtag = PK11_MechanismToAlgtag(mechanism)) == SEC_OID_UNKNOWN) {
|
|
PyErr_Format(PyExc_KeyError, "mechanism not found: %#lx", mechanism);
|
|
return NULL;
|
|
}
|
|
|
|
return PyInt_FromLong(algtag);
|
|
}
|
|
PyDoc_STRVAR(pk11_get_iv_length_doc,
|
|
"get_iv_length(mechanism) -> algtag\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Returns the length of the mechanism's initialization vector.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_get_iv_length(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
int iv_length;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:get_iv_length", &mechanism))
|
|
return NULL;
|
|
|
|
iv_length = PK11_GetIVLength(mechanism);
|
|
|
|
return PyInt_FromLong(iv_length);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_get_block_size_doc,
|
|
"get_block_size(mechanism, sec_param=None) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
sec_param : SecItem object or None\n\
|
|
mechanism parameters used to build this context or None.\n\
|
|
\n\
|
|
Get the mechanism block size\n\
|
|
");
|
|
static PyObject *
|
|
pk11_get_block_size(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"mechanism", "sec_param", NULL};
|
|
unsigned long mechanism;
|
|
SecItem *py_sec_param;
|
|
int block_size;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|O&:get_block_size", kwlist,
|
|
&mechanism, SecItemOrNoneConvert, &py_sec_param))
|
|
return NULL;
|
|
|
|
block_size = PK11_GetBlockSize(mechanism, py_sec_param ? &py_sec_param->item : NULL);
|
|
|
|
return PyInt_FromLong(block_size);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_get_pad_mechanism_doc,
|
|
"get_pad_mechanism(mechanism) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
mechanism : int\n\
|
|
key mechanism enumeration constant (CKM_*)\n\
|
|
\n\
|
|
Determine appropriate mechanism to use when padding is required.\n\
|
|
If the mechanism does not map to a padding mechanism return the mechanism.\n\
|
|
");
|
|
static PyObject *
|
|
pk11_get_pad_mechanism(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long mechanism;
|
|
unsigned long pad_mechanism;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:get_pad_mechanism", &mechanism))
|
|
return NULL;
|
|
|
|
pad_mechanism = PK11_GetPadMechanism(mechanism);
|
|
|
|
return PyInt_FromLong(pad_mechanism);
|
|
}
|
|
|
|
PyDoc_STRVAR(pk11_import_crl_doc,
|
|
"import_crl(slot, der_crl, url, type, import_options, decode_options, [user_data1, ...]) -> SignedCRL\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
slot : PK11Slot object\n\
|
|
designated PK11 slot\n\
|
|
der_crl : SecItem object\n\
|
|
signed DER CRL data encapsulated in a SecItem object.\n\
|
|
url : string\n\
|
|
URL of the CRL\n\
|
|
type : int\n\
|
|
revocation list type\n\
|
|
\n\
|
|
may be one of:\n\
|
|
- SEC_CRL_TYPE\n\
|
|
- SEC_KRL_TYPE\n\
|
|
\n\
|
|
import_options : int\n\
|
|
bit-wise OR of the following flags:\n\
|
|
- CRL_IMPORT_BYPASS_CHECKS\n\
|
|
\n\
|
|
or use CRL_IMPORT_DEFAULT_OPTIONS\n\
|
|
decode_options : int\n\
|
|
bit-wise OR of the following flags:\n\
|
|
- CRL_DECODE_DONT_COPY_DER\n\
|
|
- CRL_DECODE_SKIP_ENTRIES\n\
|
|
- CRL_DECODE_KEEP_BAD_CRL\n\
|
|
- CRL_DECODE_ADOPT_HEAP_DER\n\
|
|
\n\
|
|
or use CRL_DECODE_DEFAULT_OPTIONS\n\
|
|
user_dataN : object\n\
|
|
zero or more caller supplied parameters which will\n\
|
|
be passed to the password callback function\n\
|
|
\n\
|
|
\n\
|
|
");
|
|
static PyObject *
|
|
pk11_import_crl(PyObject *self, PyObject *args)
|
|
{
|
|
Py_ssize_t n_base_args = 6;
|
|
Py_ssize_t argc;
|
|
PyObject *parse_args = NULL;
|
|
PyObject *pin_args = NULL;
|
|
PK11Slot *py_slot;
|
|
char *url;
|
|
int type;
|
|
int import_options;
|
|
int decode_options;
|
|
SecItem *py_der_signed_crl;
|
|
CERTSignedCrl *signed_crl;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
argc = PyTuple_Size(args);
|
|
if (argc == n_base_args) {
|
|
Py_INCREF(args);
|
|
parse_args = args;
|
|
} else {
|
|
parse_args = PyTuple_GetSlice(args, 0, n_base_args);
|
|
}
|
|
|
|
if (!PyArg_ParseTuple(parse_args, "O!O!siii:import_crl",
|
|
&PK11SlotType, &py_slot,
|
|
&SecItemType, &py_der_signed_crl,
|
|
&url, &type, &import_options, &decode_options)) {
|
|
Py_DECREF(parse_args);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(parse_args);
|
|
|
|
pin_args = PyTuple_GetSlice(args, n_base_args, argc);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((signed_crl = PK11_ImportCRL(py_slot->slot, &py_der_signed_crl->item, url,
|
|
type, pin_args, import_options, NULL, decode_options)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
Py_DECREF(pin_args);
|
|
return set_nspr_error(NULL);
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
Py_DECREF(pin_args);
|
|
|
|
return SignedCRL_new_from_CERTSignedCRL(signed_crl);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_decode_der_crl_doc,
|
|
"decode_der_crl(der_crl, type=SEC_CRL_TYPE, decode_options=CRL_DECODE_DEFAULT_OPTIONS) -> SignedCRL\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
der_crl : SecItem object\n\
|
|
DER encoded CRL data encapsulated in a SECItem.\n\
|
|
type : int\n\
|
|
revocation list type\n\
|
|
\n\
|
|
may be one of:\n\
|
|
- SEC_CRL_TYPE\n\
|
|
- SEC_KRL_TYPE\n\
|
|
decode_options : int\n\
|
|
bit-wise OR of the following flags:\n\
|
|
- CRL_DECODE_DONT_COPY_DER\n\
|
|
- CRL_DECODE_SKIP_ENTRIES\n\
|
|
- CRL_DECODE_KEEP_BAD_CRL\n\
|
|
- CRL_DECODE_ADOPT_HEAP_DER\n\
|
|
\n\
|
|
or use CRL_DECODE_DEFAULT_OPTIONS\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_decode_der_crl(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"der_crl", "type", "decode_options", NULL};
|
|
SecItem *py_der_crl;
|
|
int type = SEC_CRL_TYPE;
|
|
int decode_options = CRL_DECODE_DEFAULT_OPTIONS;
|
|
CERTSignedCrl *signed_crl;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|ii:decode_der_crl", kwlist,
|
|
&SecItemType, &py_der_crl,
|
|
&py_der_crl, &type, &decode_options))
|
|
return NULL;
|
|
|
|
if ((signed_crl = CERT_DecodeDERCrlWithFlags(NULL, &py_der_crl->item, type, decode_options)) == NULL) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
return SignedCRL_new_from_CERTSignedCRL(signed_crl);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_read_der_from_file_doc,
|
|
"read_der_from_file(file, ascii=False) -> SecItem\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
file : file name or file object\n\
|
|
If string treat as file path to open and read,\n\
|
|
if file object read from file object.\n\
|
|
ascii : boolean\n\
|
|
If True treat file contents as ascii data.\n\
|
|
If PEM delimiters are found strip them.\n\
|
|
Then base64 decode the contents.\n\
|
|
\n\
|
|
Read the contents of a file and return as a SecItem object.\n\
|
|
If file is a string then treat it as a file pathname and open\n\
|
|
and read the contents of that file. If file is a file object\n\
|
|
then read the contents from the file object\n\
|
|
\n\
|
|
If the file contents begin with a PEM header then treat the\n\
|
|
the file as PEM encoded and decode the payload into DER form.\n\
|
|
Otherwise the file contents is assumed to already be in DER form.\n\
|
|
The returned SecItem contains the DER contents of the file.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_read_der_from_file(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"file", "ascii", NULL};
|
|
PyObject *file_arg;
|
|
int ascii = 0;
|
|
PyObject *py_sec_item;
|
|
PyObject *py_file, *py_file_contents;
|
|
SECItem der;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
der.data = NULL;
|
|
der.len = 0;
|
|
der.type = siBuffer;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:read_der_from_file", kwlist,
|
|
&file_arg, &ascii))
|
|
return NULL;
|
|
|
|
if (PyString_Check(file_arg) || PyUnicode_Check(file_arg)) {
|
|
if ((py_file = PyFile_FromString(PyString_AsString(file_arg), "r")) == NULL) {
|
|
return NULL;
|
|
}
|
|
} else if (PyFile_Check(file_arg)) {
|
|
py_file = file_arg;
|
|
Py_INCREF(py_file);
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "Bad file, must be pathname or file object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_file_contents = PyObject_CallMethod(py_file, "read", "")) == NULL) {
|
|
Py_DECREF(py_file);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(py_file);
|
|
|
|
if (ascii) {
|
|
char *p, *tmp, *der_begin, *der_end;
|
|
|
|
p = PyString_AsString(py_file_contents);
|
|
/* check for headers and trailers and remove them */
|
|
if ((tmp = strstr(p, "-----BEGIN")) != NULL) {
|
|
p = tmp;
|
|
tmp = PORT_Strchr(p, '\n');
|
|
if (!tmp) {
|
|
tmp = strchr(p, '\r'); /* maybe this is a MAC file */
|
|
}
|
|
if (!tmp) {
|
|
PyErr_SetString(PyExc_ValueError, "no line ending after PEM BEGIN");
|
|
Py_DECREF(py_file_contents);
|
|
return NULL;
|
|
}
|
|
p = der_begin = tmp + 1;
|
|
tmp = strstr(p, "-----END");
|
|
if (tmp != NULL) {
|
|
der_end = tmp;
|
|
*der_end = '\0';
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError, "no PEM END found");
|
|
Py_DECREF(py_file_contents);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
der_begin = p;
|
|
der_end = p + PyString_GET_SIZE(py_file_contents);
|
|
}
|
|
|
|
/* Convert to binary */
|
|
if (NSSBase64_DecodeBuffer(NULL, &der, der_begin, der_end - der_begin) == NULL) {
|
|
Py_DECREF(py_file_contents);
|
|
return set_nspr_error("Could not base64 decode contents of file");
|
|
}
|
|
py_sec_item = SecItem_new_from_SECItem(&der, SECITEM_unknown);
|
|
Py_DECREF(py_file_contents);
|
|
SECITEM_FreeItem(&der, PR_FALSE);
|
|
return py_sec_item;
|
|
}
|
|
|
|
der.data = (unsigned char *)PyString_AS_STRING(py_file_contents);
|
|
der.len = PyString_GET_SIZE(py_file_contents);
|
|
py_sec_item = SecItem_new_from_SECItem(&der, SECITEM_unknown);
|
|
Py_DECREF(py_file_contents);
|
|
return (PyObject *)py_sec_item;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_x509_key_usage_doc,
|
|
"x509_key_usage(bitstr, repr_kind=AsEnumDescription) -> (str, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
bitstr : SecItem object\n\
|
|
A SecItem containing a DER encoded bit string.\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant.\n\
|
|
(e.g. nss.KU_DIGITAL_SIGNATURE)\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
(e.g. \"Digital Signature\")\n\
|
|
AsIndex\n\
|
|
The bit position within the bit string.\n\
|
|
\n\
|
|
Return a tuple of string name for each enabled bit in the key\n\
|
|
usage bit string.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_x509_key_usage(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"bitstr", "repr_kind", NULL};
|
|
PyObject *result;
|
|
SecItem *py_sec_item;
|
|
SECItem bitstr_item;
|
|
int repr_kind = AsEnumDescription;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|i:x509_key_usage", kwlist,
|
|
&SecItemType, &py_sec_item, &repr_kind))
|
|
return NULL;
|
|
|
|
if (der_bitstring_to_nss_bitstring(&bitstr_item, &py_sec_item->item) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
result = key_usage_bitstr_to_tuple(&bitstr_item, repr_kind);
|
|
|
|
return result;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_x509_cert_type_doc,
|
|
"x509_cert_type(bitstr, repr_kind=AsEnumDescription) -> (str, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
bitstr : SecItem object\n\
|
|
A SecItem containing a DER encoded bit string.\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant.\n\
|
|
(e.g. nss.NS_CERT_TYPE_SSL_SERVER)\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
(e.g. \"SSL Server\")\n\
|
|
AsIndex\n\
|
|
The bit position within the bit string.\n\
|
|
\n\
|
|
Return a tuple of string name for each enabled bit in the key\n\
|
|
usage bit string.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_x509_cert_type(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"bitstr", "repr_kind", NULL};
|
|
PyObject *result;
|
|
SecItem *py_sec_item;
|
|
SECItem bitstr_item;
|
|
int repr_kind = AsEnumDescription;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|i:x509_cert_type", kwlist,
|
|
&SecItemType, &py_sec_item, &repr_kind))
|
|
return NULL;
|
|
|
|
if (der_bitstring_to_nss_bitstring(&bitstr_item, &py_sec_item->item) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
result = cert_type_bitstr_to_tuple(&bitstr_item, repr_kind);
|
|
|
|
return result;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_x509_ext_key_usage_doc,
|
|
"x509_ext_key_usage(sec_item, repr_kind=AsString) -> (obj, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
sec_item : SecItem object\n\
|
|
A SecItem containing a DER encoded sequence of OID's\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsObject\n\
|
|
Each extended key usage will be a SecItem object embedding\n\
|
|
the OID in DER format.\n\
|
|
AsString\n\
|
|
Each extended key usage will be a descriptive string.\n\
|
|
(e.g. \"TLS Web Server Authentication Certificate\")\n\
|
|
AsDottedDecimal\n\
|
|
Each extended key usage will be OID rendered as a dotted decimal string.\n\
|
|
(e.g. \"OID.1.3.6.1.5.5.7.3.1\")\n\
|
|
AsEnum\n\
|
|
Each extended key usage will be OID tag enumeration constant (int).\n\
|
|
(e.g. nss.SEC_OID_EXT_KEY_USAGE_SERVER_AUTH)\n\
|
|
\n\
|
|
Return a tuple of OID's according the representation kind.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_x509_ext_key_usage(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"sec_item", "repr_kind", NULL};
|
|
SecItem *py_sec_item;
|
|
int repr_kind = AsString;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,"O!|i:x509_ext_key_usage", kwlist,
|
|
&SecItemType, &py_sec_item, &repr_kind))
|
|
return NULL;
|
|
|
|
return decode_oid_sequence_to_tuple(&py_sec_item->item, repr_kind);
|
|
}
|
|
|
|
|
|
PyDoc_STRVAR(cert_x509_alt_name_doc,
|
|
"x509_alt_name(sec_item, repr_kind=AsString) -> (SecItem, ...)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
sec_item : SecItem object\n\
|
|
A SecItem containing a DER encoded alternative name extension.\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned tuple will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsObject\n\
|
|
The general name as a nss.GeneralName object\n\
|
|
AsString\n\
|
|
The general name as a string.\n\
|
|
(e.g. \"http://crl.geotrust.com/crls/secureca.crl\")\n\
|
|
AsTypeString\n\
|
|
The general name type as a string.\n\
|
|
(e.g. \"URI\")\n\
|
|
AsTypeEnum\n\
|
|
The general name type as a general name type enumerated constant.\n\
|
|
(e.g. nss.certURI )\n\
|
|
AsLabeledString\n\
|
|
The general name as a string with it's type prepended.\n\
|
|
(e.g. \"URI: http://crl.geotrust.com/crls/secureca.crl\"\n\
|
|
\n\
|
|
Return a tuple of GeneralNames according the representation kind.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_x509_alt_name(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"sec_item", "repr_kind", NULL};
|
|
SecItem *py_sec_item;
|
|
int repr_kind = AsString;
|
|
CERTGeneralName *names;
|
|
PLArenaPool *arena;
|
|
PyObject *result;
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,"O!|i:x509_alt_name", kwlist,
|
|
&SecItemType, &py_sec_item, &repr_kind))
|
|
return NULL;
|
|
|
|
if ((arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE)) == NULL ) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if ((names = CERT_DecodeAltNameExtension(arena, &py_sec_item->item)) == NULL) {
|
|
set_nspr_error(NULL);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
result = CERTGeneralName_list_to_tuple(names, repr_kind);
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return result;
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
crl_reason_to_pystr(CERTCRLEntryReasonCode reason)
|
|
{
|
|
PyObject *py_value;
|
|
PyObject *py_name;
|
|
|
|
if ((py_value = PyInt_FromLong(reason)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_name = PyDict_GetItem(crl_reason_value_to_name, py_value)) == NULL) {
|
|
Py_DECREF(py_value);
|
|
PyErr_Format(PyExc_KeyError, "CRL reason name not found: %u", reason);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_value);
|
|
Py_INCREF(py_name);
|
|
|
|
return py_name;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_crl_reason_name_doc,
|
|
"crl_reason_name(reason) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
reason : int\n\
|
|
CERTCRLEntryReasonCode constant\n\
|
|
\n\
|
|
Given a CERTCRLEntryReasonCode constant\n\
|
|
return it's name as a string\n\
|
|
");
|
|
static PyObject *
|
|
cert_crl_reason_name(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long reason;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:crl_reason_name", &reason))
|
|
return NULL;
|
|
|
|
return crl_reason_to_pystr(reason);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_crl_reason_from_name_doc,
|
|
"crl_reason_from_name(name) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
name of CERTCRLEntryReasonCode constant\n\
|
|
\n\
|
|
Given the name of a CERTCRLEntryReasonCode constant\n\
|
|
return it's integer constant\n\
|
|
The string comparison is case insensitive and will match with\n\
|
|
or without the crlEntry prefix\n\
|
|
");
|
|
static PyObject *
|
|
cert_crl_reason_from_name(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *py_name;
|
|
PyObject *py_lower_name;
|
|
PyObject *py_value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "S:crl_reason_from_name", &py_name))
|
|
return NULL;
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_value = PyDict_GetItem(crl_reason_name_to_value, py_lower_name)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "CRL reason name not found: %s", PyString_AsString(py_name));
|
|
Py_DECREF(py_lower_name);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_lower_name);
|
|
Py_INCREF(py_value);
|
|
|
|
return py_value;
|
|
}
|
|
|
|
static PyObject *
|
|
pkcs12_cipher_to_pystr(long cipher)
|
|
{
|
|
PyObject *py_value;
|
|
PyObject *py_name;
|
|
|
|
if ((py_value = PyInt_FromLong(cipher)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_name = PyDict_GetItem(pkcs12_cipher_value_to_name, py_value)) == NULL) {
|
|
Py_DECREF(py_value);
|
|
PyErr_Format(PyExc_KeyError, "PKCS12 cipher name not found: %ld", cipher);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_value);
|
|
Py_INCREF(py_name);
|
|
|
|
return py_name;
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_cipher_name_doc,
|
|
"pkcs12_cipher_name(cipher) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cipher : int\n\
|
|
PKCS12_* constant\n\
|
|
\n\
|
|
Given a PKCS12_* constant\n\
|
|
return it's name as a string\n\
|
|
");
|
|
static PyObject *
|
|
pkcs12_cipher_name(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long cipher;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:pkcs12_cipher_name", &cipher))
|
|
return NULL;
|
|
|
|
return pkcs12_cipher_to_pystr(cipher);
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_cipher_from_name_doc,
|
|
"pkcs12_cipher_from_name(name) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
name of PKCS12_* constant\n\
|
|
\n\
|
|
Given the name of a PKCS12_* constant\n\
|
|
return it's integer constant\n\
|
|
The string comparison is case insensitive and will match with\n\
|
|
or without the PKCS12\\_ prefix\n\
|
|
");
|
|
static PyObject *
|
|
pkcs12_cipher_from_name(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *py_name;
|
|
PyObject *py_lower_name;
|
|
PyObject *py_value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "S:pkcs12_cipher_from_name", &py_name))
|
|
return NULL;
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_value = PyDict_GetItem(pkcs12_cipher_name_to_value, py_lower_name)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "PKCS12 cipher name not found: %s", PyString_AsString(py_name));
|
|
Py_DECREF(py_lower_name);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_lower_name);
|
|
Py_INCREF(py_value);
|
|
|
|
return py_value;
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_map_cipher_doc,
|
|
"pkcs12_map_cipher(cipher, key_length=0) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cipher : may be one of integer, string or SecItem\n\
|
|
May be one of:\n\
|
|
\n\
|
|
* integer:: A SEC OID enumeration constant, also known as a tag\n\
|
|
(i.e. SEC_OID_*) for example SEC_OID_DES_EDE3_CBC.\n\
|
|
* string:: A string for the tag name\n\
|
|
(e.g. 'SEC_OID_DES_EDE3_CBC') The 'SEC_OID\\_' prefix is\n\
|
|
optional. A string in dotted decimal representation, for\n\
|
|
example 'OID.2.5.4.3'. The 'OID.' prefix is optional. Case\n\
|
|
is not significant.\n\
|
|
* SecItem:: A SecItem object encapsulating the OID in \n\
|
|
DER format.\n\
|
|
key_length : int\n\
|
|
The number of bits in the key. If zero a default will be selected.\n\
|
|
\n\
|
|
Given an cipher and optionally a key length, map that to a PKCS12 encryption\n\
|
|
method returned as a SEC_OID tag.\n\
|
|
");
|
|
static PyObject *
|
|
pkcs12_map_cipher(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"cipher", "key_length", NULL};
|
|
PyObject *py_cipher;
|
|
int key_length;
|
|
int tag;
|
|
SECOidTag cipher_tag = SEC_OID_UNKNOWN;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:pkcs12_map_cipher", kwlist,
|
|
&py_cipher, &key_length))
|
|
return NULL;
|
|
|
|
if ((tag = get_oid_tag_from_object(py_cipher)) == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
|
|
cipher_tag = SEC_PKCS5GetPBEAlgorithm(tag, key_length);
|
|
/* no eqivalent PKCS5/PKCS12 cipher, use the raw
|
|
* encryption tag we got and pass it directly in,
|
|
* pkcs12 will use the pkcsv5 mechanism */
|
|
if (cipher_tag == SEC_OID_PKCS5_PBES2) {
|
|
cipher_tag = tag;
|
|
} else if (cipher_tag == SEC_OID_PKCS5_PBMAC1) {
|
|
/* make sure we do not have MAC'ing ciphers here */
|
|
cipher_tag = SEC_OID_UNKNOWN;
|
|
}
|
|
} else {
|
|
cipher_tag = tag;
|
|
}
|
|
|
|
return PyInt_FromLong(cipher_tag);
|
|
}
|
|
|
|
static PyObject *
|
|
general_name_type_to_pystr(CERTGeneralNameType type)
|
|
{
|
|
PyObject *py_value;
|
|
PyObject *py_name;
|
|
|
|
if ((py_value = PyInt_FromLong(type)) == NULL) {
|
|
PyErr_SetString(PyExc_MemoryError, "unable to create object");
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_name = PyDict_GetItem(general_name_value_to_name, py_value)) == NULL) {
|
|
Py_DECREF(py_value);
|
|
PyErr_Format(PyExc_KeyError, "GeneralName type name not found: %u", type);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_value);
|
|
Py_INCREF(py_name);
|
|
|
|
return py_name;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_general_name_type_name_doc,
|
|
"general_name_type_name(type) -> string\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
type : int\n\
|
|
CERTGeneralNameType constant\n\
|
|
\n\
|
|
Given a CERTGeneralNameType constant\n\
|
|
return it's name as a string\n\
|
|
");
|
|
static PyObject *
|
|
cert_general_name_type_name(PyObject *self, PyObject *args)
|
|
{
|
|
unsigned long type;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "k:general_name_type_name", &type))
|
|
return NULL;
|
|
|
|
return general_name_type_to_pystr(type);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_general_name_type_from_name_doc,
|
|
"general_name_type_from_name(name) -> int\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
name : string\n\
|
|
name of CERTGeneralNameType constant\n\
|
|
\n\
|
|
Given the name of a CERTGeneralNameType constant\n\
|
|
return it's integer constant\n\
|
|
The string comparison is case insensitive and will match with\n\
|
|
or without the cert prefix\n\
|
|
");
|
|
static PyObject *
|
|
cert_general_name_type_from_name(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *py_name;
|
|
PyObject *py_lower_name;
|
|
PyObject *py_value;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "S:general_name_type_from_name", &py_name))
|
|
return NULL;
|
|
|
|
if ((py_lower_name = PyObject_CallMethod(py_name, "lower", NULL)) == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if ((py_value = PyDict_GetItem(general_name_name_to_value, py_lower_name)) == NULL) {
|
|
PyErr_Format(PyExc_KeyError, "GeneralName type name not found: %s", PyString_AsString(py_name));
|
|
Py_DECREF(py_lower_name);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(py_lower_name);
|
|
Py_INCREF(py_value);
|
|
|
|
return py_value;
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_cert_usage_flags_doc,
|
|
"cert_usage_flags(flags, repr_kind=AsEnumDescription) -> ['flag_name', ...]\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
flags : int\n\
|
|
certificateUsage* bit flags\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned list will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant as an integer value.\n\
|
|
AsEnumName\n\
|
|
The name of the enumerated constant as a string.\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
\n\
|
|
Given an integer with certificateUsage*\n\
|
|
(e.g. nss.certificateUsageSSLServer) bit flags return a sorted\n\
|
|
list of their string names.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_cert_usage_flags(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"flags", "repr_kind", NULL};
|
|
int flags = 0;
|
|
RepresentationKind repr_kind = AsEnumDescription;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:cert_usage_flags", kwlist,
|
|
&flags, &repr_kind))
|
|
return NULL;
|
|
|
|
return cert_usage_flags(flags, repr_kind);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_key_usage_flags_doc,
|
|
"key_usage_flags(flags, repr_kind=AsEnumName) -> ['flag_name', ...]\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
flags : int\n\
|
|
KU_* bit flags\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned list will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant as an integer value.\n\
|
|
AsEnumName\n\
|
|
The name of the enumerated constant as a string.\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
\n\
|
|
Given an integer with KU_*\n\
|
|
(e.g. nss.KU_DIGITAL_SIGNATURE) bit flags return a sorted\n\
|
|
list of their string names.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_key_usage_flags(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"flags", "repr_kind", NULL};
|
|
int flags = 0;
|
|
RepresentationKind repr_kind = AsEnumName;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:key_usage_flags", kwlist,
|
|
&flags, &repr_kind))
|
|
return NULL;
|
|
|
|
return key_usage_flags(flags, repr_kind);
|
|
}
|
|
|
|
PyDoc_STRVAR(cert_cert_type_flags_doc,
|
|
"cert_type_flags(flags, repr_kind=AsEnumName) -> ['flag_name', ...]\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
flags : int\n\
|
|
KU_* bit flags\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned list will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant as an integer value.\n\
|
|
AsEnumName\n\
|
|
The name of the enumerated constant as a string.\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
\n\
|
|
\n\
|
|
Given an integer with NS_CERT_TYPE_*\n\
|
|
(e.g. nss.NS_CERT_TYPE_SSL_SERVER) bit flags return a sorted\n\
|
|
list of their string names.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
cert_cert_type_flags(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"flags", "repr_kind", NULL};
|
|
int flags = 0;
|
|
RepresentationKind repr_kind = AsEnumName;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:cert_type_flags", kwlist,
|
|
&flags, &repr_kind))
|
|
return NULL;
|
|
|
|
return cert_type_flags(flags, repr_kind);
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_nss_init_flags_doc,
|
|
"nss_init_flags(flags, repr_kind=AsEnumName) -> ['flag_name', ...]\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
flags : int\n\
|
|
NSS_INIT* bit flags\n\
|
|
repr_kind : RepresentationKind constant\n\
|
|
Specifies what the contents of the returned list will be.\n\
|
|
May be one of:\n\
|
|
\n\
|
|
AsEnum\n\
|
|
The enumerated constant as an integer value.\n\
|
|
AsEnumName\n\
|
|
The name of the enumerated constant as a string.\n\
|
|
AsEnumDescription\n\
|
|
A friendly human readable description of the enumerated constant as a string.\n\
|
|
\n\
|
|
\n\
|
|
Given an integer with NSS_INIT*\n\
|
|
(e.g. nss.NSS_INIT_READONLY) bit flags return a sorted\n\
|
|
list of their string names.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_nss_init_flags(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"flags", "repr_kind", NULL};
|
|
int flags = 0;
|
|
RepresentationKind repr_kind = AsEnumName;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:nss_init_flags", kwlist,
|
|
&flags, &repr_kind))
|
|
return NULL;
|
|
|
|
return nss_init_flags(flags, repr_kind);
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_enable_cipher_doc,
|
|
"pkcs12_enable_cipher(cipher, enabled)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cipher : integer\n\
|
|
The PKCS12 cipher suite enumeration (e.g. `PKCS12_DES_EDE3_168`, etc.)\n\
|
|
enabled : bool or int\n\
|
|
True enables, False disables\n\
|
|
\n\
|
|
The cipher may be one of: \n\
|
|
- PKCS12_RC2_CBC_40 \n\
|
|
- PKCS12_RC2_CBC_128 \n\
|
|
- PKCS12_RC4_40 \n\
|
|
- PKCS12_RC4_128 \n\
|
|
- PKCS12_DES_56 \n\
|
|
- PKCS12_DES_EDE3_168 \n\
|
|
");
|
|
|
|
static PyObject *
|
|
pkcs12_enable_cipher(PyObject *self, PyObject *args)
|
|
{
|
|
long cipher;
|
|
int enabled;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "li:pkcs12_enable_cipher", &cipher, &enabled))
|
|
return NULL;
|
|
|
|
if (SEC_PKCS12EnableCipher(cipher, enabled ? PR_TRUE : PR_FALSE) != SECSuccess) {
|
|
PyObject *py_cipher_name = pkcs12_cipher_to_pystr(cipher);
|
|
PyObject *py_err_msg = PyString_FromFormat("Failed to %s %s (%lx) pkcs12 cipher",
|
|
enabled ? _("enable") : _("disable"),
|
|
PyString_AsString(py_cipher_name), cipher);
|
|
set_nspr_error(PyString_AsString(py_err_msg));
|
|
Py_DECREF(py_cipher_name);
|
|
Py_DECREF(py_err_msg);
|
|
return NULL;
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_enable_all_ciphers_doc,
|
|
"pkcs12_enable_all_ciphers()\n\
|
|
\n\
|
|
Enables all PKCS12 ciphers, which are: \n\
|
|
- `PKCS12_RC2_CBC_40` \n\
|
|
- `PKCS12_RC2_CBC_128` \n\
|
|
- `PKCS12_RC4_40` \n\
|
|
- `PKCS12_RC4_128` \n\
|
|
- `PKCS12_DES_56` \n\
|
|
- `PKCS12_DES_EDE3_168` \n\
|
|
");
|
|
|
|
static PyObject *
|
|
pkcs12_enable_all_ciphers(PyObject *self, PyObject *args)
|
|
{
|
|
int i;
|
|
long cipher;
|
|
long all_ciphers[] = {PKCS12_RC4_40,
|
|
PKCS12_RC4_128,
|
|
PKCS12_RC2_CBC_40,
|
|
PKCS12_RC2_CBC_128,
|
|
PKCS12_DES_56,
|
|
PKCS12_DES_EDE3_168};
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
for (i = 0; i < sizeof(all_ciphers)/sizeof(all_ciphers[0]); i++) {
|
|
cipher = all_ciphers[i];
|
|
if (SEC_PKCS12EnableCipher(cipher, PR_TRUE) != SECSuccess) {
|
|
PyObject *py_cipher_name = pkcs12_cipher_to_pystr(cipher);
|
|
PyObject *py_err_msg = PyString_FromFormat("Failed to enable %s (%lx) pkcs12 cipher",
|
|
PyString_AsString(py_cipher_name), cipher);
|
|
set_nspr_error(PyString_AsString(py_err_msg));
|
|
Py_DECREF(py_cipher_name);
|
|
Py_DECREF(py_err_msg);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_set_preferred_cipher_doc,
|
|
"pkcs12_set_preferred_cipher(cipher, enabled)\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
cipher : integer\n\
|
|
The PKCS12 cipher suite enumeration (e.g. `PKCS12_DES_EDE3_168`, etc.)\n\
|
|
enabled : bool or int\n\
|
|
True enables, False disables\n\
|
|
\n\
|
|
This function enables or disables the preferred flag on a \n\
|
|
PKCS cipher. The default preferred cipher is `PKCS12_RC2_CBC_40`.\n\
|
|
\n\
|
|
The cipher may be one of: \n\
|
|
- `PKCS12_RC2_CBC_40` \n\
|
|
- `PKCS12_RC2_CBC_128` \n\
|
|
- `PKCS12_RC4_40` \n\
|
|
- `PKCS12_RC4_128` \n\
|
|
- `PKCS12_DES_56` \n\
|
|
- `PKCS12_DES_EDE3_168` \n\
|
|
");
|
|
|
|
static PyObject *
|
|
pkcs12_set_preferred_cipher(PyObject *self, PyObject *args)
|
|
{
|
|
long cipher;
|
|
int enabled;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "li:pkcs12_set_preferred_cipher", &cipher, &enabled))
|
|
return NULL;
|
|
|
|
if (SEC_PKCS12SetPreferredCipher(cipher, enabled ? PR_TRUE : PR_FALSE) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static void
|
|
pkcs12_export_feed(void *arg, const char *buf, unsigned long len)
|
|
{
|
|
PyObject **py_encoded_buf = arg;
|
|
PyObject *py_new_string = NULL;
|
|
|
|
if (*py_encoded_buf == NULL) {
|
|
return;
|
|
}
|
|
|
|
if ((py_new_string = PyString_FromStringAndSize(buf, len)) == NULL) {
|
|
Py_CLEAR(*py_encoded_buf);
|
|
return;
|
|
}
|
|
|
|
PyString_ConcatAndDel(py_encoded_buf, py_new_string);
|
|
}
|
|
|
|
PyDoc_STRVAR(pkcs12_export_doc,
|
|
"pkcs12_export(nickname, pkcs12_password, key_cipher=SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, cert_cipher=SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, pin_args=None) \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
nickname : string\n\
|
|
Certificate nickname to search for.\n\
|
|
pkcs12_password : string\n\
|
|
The password used to protect the pkcs12_file.\n\
|
|
key_cipher : int\n\
|
|
A SEC OID TAG enumerated constant selecting the\n\
|
|
encryption for the private key (see below).\n\
|
|
Also see `nss.pkcs12_map_cipher()` for an alternative\n\
|
|
method to select the encryption cipher.\n\
|
|
cert_cipher : int\n\
|
|
A SEC OID TAG enumerated constant selecting the\n\
|
|
encryption for the certificates (see below).\n\
|
|
Also see `nss.pkcs12_map_cipher()` for an alternative\n\
|
|
method to select the encryption cipher.\n\
|
|
pin_args : tuple\n\
|
|
Extra parameters which will\n\
|
|
be passed to the password callback function.\n\
|
|
\n\
|
|
pkcs12_export() is used to export a certificate and private key pair\n\
|
|
from the NSS database in a protected manner. It produces the binary\n\
|
|
content of what is typically called a .p12 file (e.g. PKCS12). This\n\
|
|
function does not write the file, if you want to write a .p12 file\n\
|
|
you must write it's output to a file, for example:\n\
|
|
\n\
|
|
::\n\
|
|
\n\
|
|
pkcs12_data = nss.pkcs12_export(nickname, pkcs12_file_password)\n\
|
|
f = open(p12_file_path, 'w')\n\
|
|
f.write(pkcs12_data)\n\
|
|
f.close()\n\
|
|
\n\
|
|
Password Based Encryption\n\
|
|
-------------------------\n\
|
|
\n\
|
|
PKCS #12 provides for not only the protection of the private keys but\n\
|
|
also the certificate and meta-data associated with the keys. Password\n\
|
|
based encryption is used to protect private keys (i.e. key_cipher) on\n\
|
|
export to a PKCS #12 file and also the entire package when allowed\n\
|
|
(i.e. cert_cipher). If no algorithm is specified it defaults to using\n\
|
|
'PKCS #12 V2 PBE With SHA-1 And 3KEY Triple DES-CBC' for private key\n\
|
|
encryption. For historical export control reasons 'PKCS #12 V2 PBE\n\
|
|
With SHA-1 And 40 Bit RC2 CBC' is the default for the overall package\n\
|
|
encryption when not in FIPS mode and no package encryption when in\n\
|
|
FIPS mode. The private key is always protected with strong encryption\n\
|
|
by default.\n\
|
|
\n\
|
|
A list of ciphers follows, the term is the SEC OID TAG followd by a\n\
|
|
friendly description.\n\
|
|
\n\
|
|
* symmetric CBC ciphers for PKCS #5 V2:\n\
|
|
SEC_OID_DES_CBC\n\
|
|
DES-CBC.\n\
|
|
SEC_OID_RC2_CBC\n\
|
|
RC2-CBC.\n\
|
|
SEC_OID_RC5_CBC_PAD\n\
|
|
RC5-CBCPad.\n\
|
|
SEC_OID_DES_EDE3_CBC\n\
|
|
DES-EDE3-CBC.\n\
|
|
SEC_OID_AES_128_CBC\n\
|
|
AES-128-CBC.\n\
|
|
SEC_OID_AES_192_CBC\n\
|
|
AES-192-CBC.\n\
|
|
SEC_OID_AES_256_CBC\n\
|
|
AES-256-CBC.\n\
|
|
SEC_OID_CAMELLIA_128_CBC\n\
|
|
CAMELLIA-128-CBC.\n\
|
|
SEC_OID_CAMELLIA_192_CBC\n\
|
|
CAMELLIA-192-CBC.\n\
|
|
SEC_OID_CAMELLIA_256_CBC\n\
|
|
CAMELLIA-256-CBC.\n\
|
|
\n\
|
|
* PKCS #12 PBE Ciphers:\n\
|
|
SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4\n\
|
|
PKCS #12 PBE With SHA-1 and 128 Bit RC4.\n\
|
|
SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4\n\
|
|
PKCS #12 PBE With SHA-1 and 40 Bit RC4.\n\
|
|
SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC\n\
|
|
PKCS #12 PBE With SHA-1 and Triple DES-CBC.\n\
|
|
SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC\n\
|
|
PKCS #12 PBE With SHA-1 and 128 Bit RC2 CBC.\n\
|
|
SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC\n\
|
|
PKCS #12 PBE With SHA-1 and 40 Bit RC2 CBC.\n\
|
|
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4\n\
|
|
PKCS #12 V2 PBE With SHA-1 And 128 Bit RC4.\n\
|
|
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4\n\
|
|
PKCS #12 V2 PBE With SHA-1 And 40 Bit RC4.\n\
|
|
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC\n\
|
|
PKCS #12 V2 PBE With SHA-1 And 3KEY Triple DES-CBC.\n\
|
|
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC\n\
|
|
PKCS #12 V2 PBE With SHA-1 And 2KEY Triple DES-CBC.\n\
|
|
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC\n\
|
|
PKCS #12 V2 PBE With SHA-1 And 128 Bit RC2 CBC.\n\
|
|
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC\n\
|
|
PKCS #12 V2 PBE With SHA-1 And 40 Bit RC2 CBC.\n\
|
|
\n\
|
|
* PKCS #5 PBE Ciphers:\n\
|
|
SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC\n\
|
|
PKCS #5 Password Based Encryption with MD2 and DES-CBC.\n\
|
|
SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC\n\
|
|
PKCS #5 Password Based Encryption with MD5 and DES-CBC.\n\
|
|
SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC\n\
|
|
PKCS #5 Password Based Encryption with SHA-1 and DES-CBC.\n\
|
|
\n\
|
|
");
|
|
|
|
static PyObject *
|
|
pkcs12_export(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"nickname", "pkcs12_password", "key_cipher",
|
|
"cert_cipher", "pin_args", NULL};
|
|
char *utf8_nickname = NULL;
|
|
char *utf8_pkcs12_password = NULL;
|
|
int utf8_pkcs12_password_len = 0;
|
|
unsigned int key_cipher = SEC_OID_UNKNOWN;
|
|
unsigned int cert_cipher = SEC_OID_UNKNOWN;
|
|
PyObject *pin_args = Py_None;
|
|
PyObject *py_encoded_buf = NULL;
|
|
|
|
SEC_PKCS12ExportContext *export_ctx = NULL;
|
|
SEC_PKCS12SafeInfo *key_safe = NULL, *cert_safe = NULL;
|
|
SECItem utf8_pkcs12_password_item = {siUTF8String, NULL, 0};
|
|
CERTCertList* cert_list = NULL;
|
|
CERTCertListNode* node = NULL;
|
|
PK11SlotInfo* slot = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
/*
|
|
* NSS WART
|
|
* Despite the name UCS2_ASCIIConversion it's really UCS2 <-> arbitrary_encoding.
|
|
*/
|
|
PORT_SetUCS2_ASCIIConversionFunction(secport_ucs2_to_utf8);
|
|
|
|
key_cipher = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
|
|
cert_cipher = PK11_IsFIPS() ? SEC_OID_UNKNOWN : SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "eses#|IIO!:pkcs12_export", kwlist,
|
|
"utf-8", &utf8_nickname,
|
|
"utf-8", &utf8_pkcs12_password, &utf8_pkcs12_password_len,
|
|
&key_cipher, &cert_cipher,
|
|
TupleOrNoneConvert, &pin_args))
|
|
return NULL;
|
|
|
|
utf8_pkcs12_password_item.len = utf8_pkcs12_password_len;
|
|
utf8_pkcs12_password_item.data = (unsigned char *)utf8_pkcs12_password;
|
|
if (PyNone_Check(pin_args)) {
|
|
pin_args = NULL;
|
|
}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
if ((cert_list = PK11_FindCertsFromNickname(utf8_nickname, pin_args)) == NULL) {
|
|
Py_BLOCK_THREADS
|
|
PyErr_Format(PyExc_ValueError, "failed to find certs for nickname = \"%s\"", utf8_nickname);
|
|
goto exit;
|
|
}
|
|
Py_END_ALLOW_THREADS
|
|
|
|
/* User certs are those with private keys, retain only those */
|
|
if (CERT_FilterCertListForUserCerts(cert_list) != SECSuccess ||
|
|
CERT_LIST_EMPTY(cert_list)) {
|
|
PyErr_Format(PyExc_ValueError, "no certs with keys for nickname = \"%s\"", utf8_nickname);
|
|
goto exit;
|
|
}
|
|
|
|
if (cert_list) {
|
|
CERTCertificate* cert = NULL;
|
|
node = CERT_LIST_HEAD(cert_list);
|
|
if (node) {
|
|
cert = node->cert;
|
|
}
|
|
if (cert) {
|
|
/* Use the slot from the first matching certificate to
|
|
* create the context. This is for keygen */
|
|
slot = cert->slot;
|
|
}
|
|
}
|
|
|
|
if (!slot) {
|
|
PyErr_SetString(PyExc_ValueError, "cert does not have a slot");
|
|
goto exit;
|
|
}
|
|
|
|
if ((export_ctx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, pin_args)) == NULL) {
|
|
set_nspr_error("export context creation failed");
|
|
goto exit;
|
|
}
|
|
|
|
if (SEC_PKCS12AddPasswordIntegrity(export_ctx, &utf8_pkcs12_password_item, SEC_OID_SHA1) != SECSuccess) {
|
|
set_nspr_error("PKCS12 add password integrity failed");
|
|
goto exit;
|
|
}
|
|
|
|
for (node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node,cert_list); node = CERT_LIST_NEXT(node)) {
|
|
CERTCertificate* cert = node->cert;
|
|
if (!cert->slot) {
|
|
PyErr_SetString(PyExc_ValueError, "cert does not have a slot");
|
|
goto exit;
|
|
}
|
|
|
|
key_safe = SEC_PKCS12CreateUnencryptedSafe(export_ctx);
|
|
if (cert_cipher == SEC_OID_UNKNOWN) {
|
|
cert_safe = key_safe;
|
|
} else {
|
|
cert_safe = SEC_PKCS12CreatePasswordPrivSafe(export_ctx, &utf8_pkcs12_password_item, cert_cipher);
|
|
}
|
|
|
|
if (!cert_safe || !key_safe) {
|
|
PyErr_SetString(PyExc_ValueError, "key or cert safe creation failed");
|
|
goto exit;
|
|
}
|
|
|
|
if (SEC_PKCS12AddCertAndKey(export_ctx, cert_safe, NULL, cert,
|
|
CERT_GetDefaultCertDB(), key_safe, NULL,
|
|
PR_TRUE, &utf8_pkcs12_password_item, key_cipher) != SECSuccess) {
|
|
set_nspr_error("add cert and key failed");
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if ((py_encoded_buf = PyString_FromStringAndSize(NULL, 0)) == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
if (SEC_PKCS12Encode(export_ctx, pkcs12_export_feed, &py_encoded_buf) != SECSuccess) {
|
|
set_nspr_error("PKCS12 encode failed");
|
|
Py_CLEAR(py_encoded_buf);
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if (utf8_nickname) {
|
|
PyMem_Free(utf8_nickname);
|
|
}
|
|
if (utf8_pkcs12_password) {
|
|
PyMem_Free(utf8_pkcs12_password);
|
|
}
|
|
if (cert_list) {
|
|
CERT_DestroyCertList(cert_list);
|
|
}
|
|
if (export_ctx) {
|
|
SEC_PKCS12DestroyExportContext(export_ctx);
|
|
}
|
|
|
|
return py_encoded_buf;
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_fingerprint_format_lines_doc,
|
|
"fingerprint_format_lines(data, level=0) -> \n\
|
|
\n\
|
|
:Parameters:\n\
|
|
data : SecItem or str or any buffer compatible object\n\
|
|
Data to initialize the certificate request from, must be in DER format\n\
|
|
level : integer\n\
|
|
Initial indentation level, all subsequent indents are relative\n\
|
|
to this starting level.\n\
|
|
\n\
|
|
Generates digests of data (i.e. fingerprint) and formats\n\
|
|
it into line tuples for text output.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_fingerprint_format_lines(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
static char *kwlist[] = {"data", "level", NULL};
|
|
int level = 0;
|
|
PyObject *py_data = NULL;
|
|
SECItem tmp_item;
|
|
SECItem *der_item = NULL;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:fingerprint_format_lines", kwlist,
|
|
&py_data, &level))
|
|
return NULL;
|
|
|
|
if (PySecItem_Check(py_data)) {
|
|
der_item = &((SecItem *)py_data)->item;
|
|
} else if (PyObject_CheckReadBuffer(py_data)) {
|
|
unsigned char *data = NULL;
|
|
Py_ssize_t data_len;
|
|
|
|
if (PyObject_AsReadBuffer(py_data, (void *)&data, &data_len))
|
|
return NULL;
|
|
|
|
tmp_item.data = data;
|
|
tmp_item.len = data_len;
|
|
der_item = &tmp_item;
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "data must be SecItem or buffer compatible");
|
|
return NULL;
|
|
}
|
|
|
|
return fingerprint_format_lines(der_item, level);
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_get_use_pkix_for_validation_doc,
|
|
"get_use_pkix_for_validation() -> flag\n\
|
|
\n\
|
|
Returns the current value of the flag used to enable or disable the\n\
|
|
use of PKIX for certificate validation. See also:\n\
|
|
`set_use_pkix_for_validation`.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_get_use_pkix_for_validation(PyObject *self, PyObject *args)
|
|
{
|
|
PRBool flag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
flag = CERT_GetUsePKIXForValidation();
|
|
|
|
if (flag) {
|
|
Py_RETURN_TRUE;
|
|
} else {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
}
|
|
|
|
PyDoc_STRVAR(nss_set_use_pkix_for_validation_doc,
|
|
"set_use_pkix_for_validation(flag) -> prev_flag\n\
|
|
\n\
|
|
:Parameters:\n\
|
|
flag : boolean\n\
|
|
Boolean flag, True to enable PKIX validation,\n\
|
|
False to disable PKIX validation.\n\
|
|
\n\
|
|
Sets the flag to enable or disable the use of PKIX for certificate\n\
|
|
validation. Returns the previous value of the flag.\n\
|
|
See also: `get_use_pkix_for_validation`.\n\
|
|
");
|
|
|
|
static PyObject *
|
|
nss_set_use_pkix_for_validation(PyObject *self, PyObject *args)
|
|
{
|
|
int flag;
|
|
PRBool prev_flag;
|
|
|
|
TraceMethodEnter(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "i:set_use_pkix_for_validation",
|
|
&flag))
|
|
return NULL;
|
|
|
|
prev_flag = CERT_GetUsePKIXForValidation();
|
|
|
|
if (CERT_SetUsePKIXForValidation(flag ? PR_TRUE : PR_FALSE) != SECSuccess) {
|
|
return set_nspr_error(NULL);
|
|
}
|
|
|
|
if (prev_flag) {
|
|
Py_RETURN_TRUE;
|
|
} else {
|
|
Py_RETURN_FALSE;
|
|
}
|
|
}
|
|
|
|
/* List of functions exported by this module. */
|
|
static PyMethodDef
|
|
module_methods[] = {
|
|
{"nss_is_initialized", (PyCFunction)nss_nss_is_initialized, METH_NOARGS, nss_nss_is_initialized_doc},
|
|
{"nss_init", (PyCFunction)nss_nss_init, METH_VARARGS, nss_nss_init_doc},
|
|
{"nss_init_read_write", (PyCFunction)nss_nss_init_read_write, METH_VARARGS, nss_nss_init_read_write_doc},
|
|
{"nss_init_nodb", (PyCFunction)nss_init_nodb, METH_NOARGS, nss_init_nodb_doc},
|
|
{"nss_initialize", (PyCFunction)nss_nss_initialize, METH_VARARGS|METH_KEYWORDS, nss_nss_initialize_doc},
|
|
{"nss_init_context", (PyCFunction)nss_nss_init_context, METH_VARARGS|METH_KEYWORDS, nss_nss_init_context_doc},
|
|
{"nss_shutdown", (PyCFunction)nss_nss_shutdown, METH_NOARGS, nss_nss_shutdown_doc},
|
|
{"nss_shutdown_context", (PyCFunction)nss_nss_shutdown_context, METH_VARARGS, nss_nss_shutdown_context_doc},
|
|
{"dump_certificate_cache_info", (PyCFunction)nss_dump_certificate_cache_info, METH_NOARGS, nss_dump_certificate_cache_info_doc},
|
|
{"set_password_callback", (PyCFunction)pk11_set_password_callback, METH_VARARGS, pk11_set_password_callback_doc},
|
|
{"list_certs", (PyCFunction)pk11_list_certs, METH_VARARGS, pk11_list_certs_doc},
|
|
{"find_certs_from_email_addr", (PyCFunction)pk11_find_certs_from_email_addr, METH_VARARGS, pk11_find_certs_from_email_addr_doc},
|
|
{"find_certs_from_nickname", (PyCFunction)pk11_find_certs_from_nickname, METH_VARARGS, pk11_find_certs_from_nickname_doc},
|
|
{"find_cert_from_nickname", (PyCFunction)pk11_find_cert_from_nickname, METH_VARARGS, pk11_find_cert_from_nickname_doc},
|
|
{"find_key_by_any_cert", (PyCFunction)pk11_find_key_by_any_cert, METH_VARARGS, pk11_find_key_by_any_cert_doc},
|
|
{"generate_random", (PyCFunction)pk11_generate_random, METH_VARARGS, pk11_generate_random_doc},
|
|
{"get_default_certdb", (PyCFunction)cert_get_default_certdb, METH_NOARGS, cert_get_default_certdb_doc},
|
|
{"get_cert_nicknames", (PyCFunction)cert_get_cert_nicknames, METH_VARARGS, cert_get_cert_nicknames_doc},
|
|
{"data_to_hex", (PyCFunction)cert_data_to_hex, METH_VARARGS|METH_KEYWORDS, cert_data_to_hex_doc},
|
|
{"read_hex", (PyCFunction)read_hex, METH_VARARGS|METH_KEYWORDS, read_hex_doc},
|
|
{"hash_buf", (PyCFunction)pk11_hash_buf, METH_VARARGS, pk11_hash_buf_doc},
|
|
{"md5_digest", (PyCFunction)pk11_md5_digest, METH_VARARGS, pk11_md5_digest_doc},
|
|
{"sha1_digest", (PyCFunction)pk11_sha1_digest, METH_VARARGS, pk11_sha1_digest_doc},
|
|
{"sha256_digest", (PyCFunction)pk11_sha256_digest, METH_VARARGS, pk11_sha256_digest_doc},
|
|
{"sha512_digest", (PyCFunction)pk11_sha512_digest, METH_VARARGS, pk11_sha512_digest_doc},
|
|
{"indented_format", (PyCFunction)py_indented_format, METH_VARARGS|METH_KEYWORDS, py_indented_format_doc},
|
|
{"make_line_fmt_tuples", (PyCFunction)py_make_line_fmt_tuples, METH_VARARGS|METH_KEYWORDS, py_make_line_fmt_tuples_doc},
|
|
{"der_universal_secitem_fmt_lines", (PyCFunction)cert_der_universal_secitem_fmt_lines, METH_VARARGS|METH_KEYWORDS, cert_der_universal_secitem_fmt_lines_doc},
|
|
{"oid_str", (PyCFunction)cert_oid_str, METH_VARARGS, cert_oid_str_doc},
|
|
{"oid_tag_name", (PyCFunction)cert_oid_tag_name, METH_VARARGS, cert_oid_tag_name_doc},
|
|
{"oid_tag", (PyCFunction)cert_oid_tag, METH_VARARGS, cert_oid_tag_doc},
|
|
{"oid_dotted_decimal", (PyCFunction)cert_oid_dotted_decimal, METH_VARARGS, cert_oid_dotted_decimal_doc},
|
|
{"key_mechanism_type_name", (PyCFunction)pk11_key_mechanism_type_name, METH_VARARGS, pk11_key_mechanism_type_name_doc},
|
|
{"key_mechanism_type_from_name", (PyCFunction)pk11_key_mechanism_type_from_name, METH_VARARGS, pk11_key_mechanism_type_from_name_doc},
|
|
{"pk11_attribute_type_name", (PyCFunction)pk11_pk11_attribute_type_name, METH_VARARGS, pk11_attribute_type_name_doc},
|
|
{"pk11_attribute_type_from_name", (PyCFunction)pk11_pk11_attribute_type_from_name, METH_VARARGS, pk11_pk11_attribute_type_from_name_doc},
|
|
{"cert_crl_reason_name", (PyCFunction)cert_crl_reason_name, METH_VARARGS, cert_crl_reason_name_doc},
|
|
{"cert_crl_reason_from_name", (PyCFunction)cert_crl_reason_from_name, METH_VARARGS, cert_crl_reason_from_name_doc},
|
|
{"cert_general_name_type_name", (PyCFunction)cert_general_name_type_name, METH_VARARGS, cert_general_name_type_name_doc},
|
|
{"cert_general_name_type_from_name", (PyCFunction)cert_general_name_type_from_name, METH_VARARGS, cert_general_name_type_from_name_doc},
|
|
{"pk11_disabled_reason_str", (PyCFunction)pk11_pk11_disabled_reason_str, METH_VARARGS, pk11_disabled_reason_str_doc},
|
|
{"pk11_disabled_reason_name", (PyCFunction)pk11_pk11_disabled_reason_name, METH_VARARGS, pk11_disabled_reason_name_doc},
|
|
{"pk11_logout_all", (PyCFunction)pk11_pk11_logout_all, METH_NOARGS, pk11_pk11_logout_all_doc},
|
|
{"get_best_slot", (PyCFunction)pk11_get_best_slot, METH_VARARGS, pk11_get_best_slot_doc},
|
|
{"get_internal_slot", (PyCFunction)pk11_get_internal_slot, METH_NOARGS, pk11_get_internal_slot_doc},
|
|
{"get_internal_key_slot", (PyCFunction)pk11_get_internal_key_slot, METH_NOARGS, pk11_get_internal_key_slot_doc},
|
|
{"find_slot_by_name", (PyCFunction)pk11_find_slot_by_name, METH_VARARGS, pk11_find_slot_by_name_doc},
|
|
{"create_context_by_sym_key", (PyCFunction)pk11_create_context_by_sym_key, METH_VARARGS|METH_KEYWORDS, pk11_create_context_by_sym_key_doc},
|
|
{"import_sym_key", (PyCFunction)pk11_import_sym_key, METH_VARARGS, pk11_import_sym_key_doc},
|
|
{"pub_wrap_sym_key", (PyCFunction)pk11_pub_wrap_sym_key, METH_VARARGS, pk11_pub_wrap_sym_key_doc},
|
|
{"create_digest_context", (PyCFunction)pk11_create_digest_context, METH_VARARGS, pk11_create_digest_context_doc},
|
|
{"param_from_iv", (PyCFunction)pk11_param_from_iv, METH_VARARGS|METH_KEYWORDS, pk11_param_from_iv_doc},
|
|
{"param_from_algid", (PyCFunction)pk11_param_from_algid, METH_VARARGS, pk11_param_from_algid_doc},
|
|
{"generate_new_param", (PyCFunction)pk11_generate_new_param, METH_VARARGS|METH_KEYWORDS, pk11_generate_new_param_doc},
|
|
{"algtag_to_mechanism", (PyCFunction)pk11_algtag_to_mechanism, METH_VARARGS, pk11_algtag_to_mechanism_doc},
|
|
{"mechanism_to_algtag", (PyCFunction)pk11_mechanism_to_algtag, METH_VARARGS, pk11_mechanism_to_algtag_doc},
|
|
{"get_iv_length", (PyCFunction)pk11_get_iv_length, METH_VARARGS, pk11_get_iv_length_doc},
|
|
{"get_block_size", (PyCFunction)pk11_get_block_size, METH_VARARGS|METH_KEYWORDS, pk11_get_block_size_doc},
|
|
{"get_pad_mechanism", (PyCFunction)pk11_get_pad_mechanism, METH_VARARGS, pk11_get_pad_mechanism_doc},
|
|
{"import_crl", (PyCFunction)pk11_import_crl, METH_VARARGS, pk11_import_crl_doc},
|
|
{"need_pw_init", (PyCFunction)pk11_pk11_need_pw_init, METH_NOARGS, pk11_pk11_need_pw_init_doc},
|
|
{"token_exists", (PyCFunction)pk11_pk11_token_exists, METH_NOARGS, pk11_pk11_token_exists_doc},
|
|
{"is_fips", (PyCFunction)pk11_pk11_is_fips, METH_NOARGS, pk11_pk11_is_fips_doc},
|
|
{"decode_der_crl", (PyCFunction)cert_decode_der_crl, METH_VARARGS|METH_KEYWORDS, cert_decode_der_crl_doc},
|
|
{"read_der_from_file", (PyCFunction)cert_read_der_from_file, METH_VARARGS|METH_KEYWORDS, cert_read_der_from_file_doc},
|
|
{"x509_key_usage", (PyCFunction)cert_x509_key_usage, METH_VARARGS|METH_KEYWORDS, cert_x509_key_usage_doc},
|
|
{"x509_cert_type", (PyCFunction)cert_x509_cert_type, METH_VARARGS|METH_KEYWORDS, cert_x509_cert_type_doc},
|
|
{"x509_ext_key_usage", (PyCFunction)cert_x509_ext_key_usage, METH_VARARGS|METH_KEYWORDS, cert_x509_ext_key_usage_doc},
|
|
{"x509_alt_name", (PyCFunction)cert_x509_alt_name, METH_VARARGS|METH_KEYWORDS, cert_x509_alt_name_doc},
|
|
{"cert_usage_flags", (PyCFunction)cert_cert_usage_flags, METH_VARARGS|METH_KEYWORDS, cert_cert_usage_flags_doc},
|
|
{"key_usage_flags", (PyCFunction)cert_key_usage_flags, METH_VARARGS|METH_KEYWORDS, cert_key_usage_flags_doc},
|
|
{"cert_type_flags", (PyCFunction)cert_cert_type_flags, METH_VARARGS|METH_KEYWORDS, cert_cert_type_flags_doc},
|
|
{"nss_init_flags", (PyCFunction)nss_nss_init_flags, METH_VARARGS|METH_KEYWORDS, nss_nss_init_flags_doc},
|
|
{"pkcs12_enable_cipher", (PyCFunction)pkcs12_enable_cipher, METH_VARARGS, pkcs12_enable_cipher_doc},
|
|
{"pkcs12_enable_all_ciphers", (PyCFunction)pkcs12_enable_all_ciphers, METH_NOARGS, pkcs12_enable_all_ciphers_doc},
|
|
{"pkcs12_set_preferred_cipher", (PyCFunction)pkcs12_set_preferred_cipher, METH_VARARGS, pkcs12_set_preferred_cipher_doc},
|
|
{"pkcs12_cipher_name", (PyCFunction)pkcs12_cipher_name, METH_VARARGS, pkcs12_cipher_name_doc},
|
|
{"pkcs12_cipher_from_name", (PyCFunction)pkcs12_cipher_from_name, METH_VARARGS, pkcs12_cipher_from_name_doc},
|
|
{"pkcs12_map_cipher", (PyCFunction)pkcs12_map_cipher, METH_VARARGS|METH_KEYWORDS, pkcs12_map_cipher_doc},
|
|
{"pkcs12_set_nickname_collision_callback", (PyCFunction)PKCS12_pkcs12_set_nickname_collision_callback, METH_VARARGS, PKCS12_pkcs12_set_nickname_collision_callback_doc},
|
|
{"pkcs12_export", (PyCFunction)pkcs12_export, METH_VARARGS|METH_KEYWORDS, pkcs12_export_doc},
|
|
{"fingerprint_format_lines", (PyCFunction)nss_fingerprint_format_lines, METH_VARARGS|METH_KEYWORDS, nss_fingerprint_format_lines_doc},
|
|
{"get_use_pkix_for_validation", (PyCFunction)nss_get_use_pkix_for_validation, METH_NOARGS, nss_get_use_pkix_for_validation_doc},
|
|
{"set_use_pkix_for_validation", (PyCFunction)nss_set_use_pkix_for_validation, METH_VARARGS, nss_set_use_pkix_for_validation_doc},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
/* ============================== Module Exports ============================= */
|
|
|
|
static PyNSPR_NSS_C_API_Type nspr_nss_c_api =
|
|
{
|
|
&PK11SlotType,
|
|
&CertDBType,
|
|
&CertificateType,
|
|
&PrivateKeyType,
|
|
&SecItemType,
|
|
Certificate_new_from_CERTCertificate,
|
|
PrivateKey_new_from_SECKEYPrivateKey,
|
|
SecItem_new_from_SECItem,
|
|
cert_distnames_new_from_CERTDistNames,
|
|
cert_distnames_as_CERTDistNames
|
|
};
|
|
|
|
/* ============================== Module Construction ============================= */
|
|
|
|
PyDoc_STRVAR(module_doc,
|
|
"This module implements the NSS functions\n\
|
|
\n\
|
|
");
|
|
|
|
PyMODINIT_FUNC
|
|
initnss(void)
|
|
{
|
|
PyObject *m;
|
|
|
|
if (import_nspr_error_c_api() < 0) {
|
|
return;
|
|
}
|
|
|
|
if ((m = Py_InitModule3("nss.nss", module_methods, module_doc)) == NULL) {
|
|
return;
|
|
}
|
|
|
|
if ((empty_tuple = PyTuple_New(0)) == NULL) {
|
|
return;
|
|
}
|
|
Py_INCREF(empty_tuple);
|
|
|
|
TYPE_READY(SecItemType);
|
|
TYPE_READY(AlgorithmIDType);
|
|
TYPE_READY(RSAGenParamsType);
|
|
TYPE_READY(KEYPQGParamsType);
|
|
TYPE_READY(RSAPublicKeyType);
|
|
TYPE_READY(DSAPublicKeyType);
|
|
TYPE_READY(SignedDataType);
|
|
TYPE_READY(PublicKeyType);
|
|
TYPE_READY(SubjectPublicKeyInfoType);
|
|
TYPE_READY(CertDBType);
|
|
TYPE_READY(CertificateExtensionType);
|
|
TYPE_READY(CertificateType);
|
|
TYPE_READY(PrivateKeyType);
|
|
TYPE_READY(SignedCRLType);
|
|
TYPE_READY(PK11SlotType);
|
|
TYPE_READY(PK11SymKeyType);
|
|
TYPE_READY(PK11ContextType);
|
|
TYPE_READY(CRLDistributionPtType);
|
|
TYPE_READY(CRLDistributionPtsType);
|
|
TYPE_READY(AVAType);
|
|
TYPE_READY(RDNType);
|
|
TYPE_READY(DNType);
|
|
TYPE_READY(GeneralNameType);
|
|
TYPE_READY(AuthKeyIDType);
|
|
TYPE_READY(BasicConstraintsType);
|
|
TYPE_READY(CertificateRequestType);
|
|
TYPE_READY(InitParametersType);
|
|
TYPE_READY(InitContextType);
|
|
TYPE_READY(PKCS12DecodeItemType);
|
|
TYPE_READY(PKCS12DecoderType);
|
|
TYPE_READY(CertVerifyLogNodeType);
|
|
TYPE_READY(CertVerifyLogType);
|
|
|
|
/* Export C API */
|
|
if (PyModule_AddObject(m, "_C_API", PyCObject_FromVoidPtr((void *)&nspr_nss_c_api, NULL)) != 0) {
|
|
return;
|
|
}
|
|
|
|
AddIntConstant(OCTETS_PER_LINE_DEFAULT);
|
|
PyModule_AddStringMacro(m, HEX_SEPARATOR_DEFAULT);
|
|
|
|
AddIntConstant(AsObject);
|
|
AddIntConstant(AsString);
|
|
AddIntConstant(AsTypeString);
|
|
AddIntConstant(AsTypeEnum);
|
|
AddIntConstant(AsLabeledString);
|
|
AddIntConstant(AsEnum);
|
|
AddIntConstant(AsEnumName);
|
|
AddIntConstant(AsEnumDescription);
|
|
AddIntConstant(AsIndex);
|
|
AddIntConstant(AsDottedDecimal);
|
|
|
|
AddIntConstant(generalName);
|
|
AddIntConstant(relativeDistinguishedName);
|
|
|
|
AddIntConstant(PK11CertListUnique);
|
|
AddIntConstant(PK11CertListUser);
|
|
AddIntConstant(PK11CertListRootUnique);
|
|
AddIntConstant(PK11CertListCA);
|
|
AddIntConstant(PK11CertListCAUnique);
|
|
AddIntConstant(PK11CertListUserUnique);
|
|
AddIntConstant(PK11CertListAll);
|
|
|
|
AddIntConstant(certUsageSSLClient);
|
|
AddIntConstant(certUsageSSLServer);
|
|
AddIntConstant(certUsageSSLServerWithStepUp);
|
|
AddIntConstant(certUsageSSLCA);
|
|
AddIntConstant(certUsageEmailSigner);
|
|
AddIntConstant(certUsageEmailRecipient);
|
|
AddIntConstant(certUsageObjectSigner);
|
|
AddIntConstant(certUsageUserCertImport);
|
|
AddIntConstant(certUsageVerifyCA);
|
|
AddIntConstant(certUsageProtectedObjectSigner);
|
|
AddIntConstant(certUsageStatusResponder);
|
|
AddIntConstant(certUsageAnyCA);
|
|
|
|
AddIntConstant(certificateUsageCheckAllUsages);
|
|
AddIntConstant(certificateUsageSSLClient);
|
|
AddIntConstant(certificateUsageSSLServer);
|
|
AddIntConstant(certificateUsageSSLServerWithStepUp);
|
|
AddIntConstant(certificateUsageSSLCA);
|
|
AddIntConstant(certificateUsageEmailSigner);
|
|
AddIntConstant(certificateUsageEmailRecipient);
|
|
AddIntConstant(certificateUsageObjectSigner);
|
|
AddIntConstant(certificateUsageUserCertImport);
|
|
AddIntConstant(certificateUsageVerifyCA);
|
|
AddIntConstant(certificateUsageProtectedObjectSigner);
|
|
AddIntConstant(certificateUsageStatusResponder);
|
|
AddIntConstant(certificateUsageAnyCA);
|
|
|
|
AddIntConstant(NSS_INIT_READONLY);
|
|
AddIntConstant(NSS_INIT_NOCERTDB);
|
|
AddIntConstant(NSS_INIT_NOMODDB);
|
|
AddIntConstant(NSS_INIT_FORCEOPEN);
|
|
AddIntConstant(NSS_INIT_NOROOTINIT);
|
|
AddIntConstant(NSS_INIT_OPTIMIZESPACE);
|
|
AddIntConstant(NSS_INIT_PK11THREADSAFE);
|
|
AddIntConstant(NSS_INIT_PK11RELOAD);
|
|
AddIntConstant(NSS_INIT_NOPK11FINALIZE);
|
|
AddIntConstant(NSS_INIT_RESERVED);
|
|
AddIntConstant(NSS_INIT_COOPERATE);
|
|
|
|
AddIntConstant(ssl_kea_null);
|
|
AddIntConstant(ssl_kea_rsa);
|
|
AddIntConstant(ssl_kea_dh);
|
|
AddIntConstant(ssl_kea_fortezza);
|
|
AddIntConstant(ssl_kea_ecdh);
|
|
|
|
AddIntConstant(nullKey);
|
|
AddIntConstant(rsaKey);
|
|
AddIntConstant(dsaKey);
|
|
AddIntConstant(fortezzaKey);
|
|
AddIntConstant(dhKey);
|
|
AddIntConstant(keaKey);
|
|
AddIntConstant(ecKey);
|
|
|
|
AddIntConstant(SEC_CERT_NICKNAMES_ALL);
|
|
AddIntConstant(SEC_CERT_NICKNAMES_USER);
|
|
AddIntConstant(SEC_CERT_NICKNAMES_SERVER);
|
|
AddIntConstant(SEC_CERT_NICKNAMES_CA);
|
|
|
|
AddIntConstant(SEC_CRL_TYPE);
|
|
AddIntConstant(SEC_KRL_TYPE);
|
|
|
|
AddIntConstant(CRL_DECODE_DEFAULT_OPTIONS);
|
|
AddIntConstant(CRL_DECODE_DONT_COPY_DER);
|
|
AddIntConstant(CRL_DECODE_SKIP_ENTRIES);
|
|
AddIntConstant(CRL_DECODE_KEEP_BAD_CRL);
|
|
AddIntConstant(CRL_DECODE_ADOPT_HEAP_DER);
|
|
|
|
AddIntConstant(CRL_IMPORT_DEFAULT_OPTIONS);
|
|
AddIntConstant(CRL_IMPORT_BYPASS_CHECKS);
|
|
|
|
|
|
AddIntConstant(secCertTimeValid);
|
|
AddIntConstant(secCertTimeExpired);
|
|
AddIntConstant(secCertTimeNotValidYet);
|
|
|
|
AddIntConstant(KU_DIGITAL_SIGNATURE);
|
|
AddIntConstant(KU_NON_REPUDIATION);
|
|
AddIntConstant(KU_KEY_ENCIPHERMENT);
|
|
AddIntConstant(KU_DATA_ENCIPHERMENT);
|
|
AddIntConstant(KU_KEY_AGREEMENT);
|
|
AddIntConstant(KU_KEY_CERT_SIGN);
|
|
AddIntConstant(KU_CRL_SIGN);
|
|
AddIntConstant(KU_ENCIPHER_ONLY);
|
|
AddIntConstant(KU_ALL);
|
|
AddIntConstant(KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION);
|
|
AddIntConstant(KU_KEY_AGREEMENT_OR_ENCIPHERMENT);
|
|
AddIntConstant(KU_NS_GOVT_APPROVED);
|
|
|
|
/***************************************************************************
|
|
* CRL Reason
|
|
***************************************************************************/
|
|
|
|
if ((crl_reason_name_to_value = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
if ((crl_reason_value_to_name = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
|
|
#define ExportConstant(constant) \
|
|
if (_AddIntConstantWithLookup(m, #constant, constant, \
|
|
"crlEntry", crl_reason_name_to_value, crl_reason_value_to_name) < 0) return;
|
|
|
|
ExportConstant(crlEntryReasonUnspecified);
|
|
ExportConstant(crlEntryReasonKeyCompromise);
|
|
ExportConstant(crlEntryReasonCaCompromise);
|
|
ExportConstant(crlEntryReasonAffiliationChanged);
|
|
ExportConstant(crlEntryReasonSuperseded);
|
|
ExportConstant(crlEntryReasonCessationOfOperation);
|
|
ExportConstant(crlEntryReasoncertificatedHold);
|
|
ExportConstant(crlEntryReasonRemoveFromCRL);
|
|
ExportConstant(crlEntryReasonPrivilegeWithdrawn);
|
|
ExportConstant(crlEntryReasonAaCompromise);
|
|
|
|
#undef ExportConstant
|
|
|
|
/***************************************************************************
|
|
* General Name Types
|
|
***************************************************************************/
|
|
|
|
if ((general_name_name_to_value = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
if ((general_name_value_to_name = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
|
|
#define ExportConstant(constant) \
|
|
if (_AddIntConstantWithLookup(m, #constant, constant, \
|
|
"cert", general_name_name_to_value, general_name_value_to_name) < 0) return;
|
|
|
|
ExportConstant(certOtherName);
|
|
ExportConstant(certRFC822Name);
|
|
ExportConstant(certDNSName);
|
|
ExportConstant(certX400Address);
|
|
ExportConstant(certDirectoryName);
|
|
ExportConstant(certEDIPartyName);
|
|
ExportConstant(certURI);
|
|
ExportConstant(certIPAddress);
|
|
ExportConstant(certRegisterID);
|
|
|
|
#undef ExportConstant
|
|
|
|
/***************************************************************************
|
|
* Mechanism Types
|
|
***************************************************************************/
|
|
|
|
if ((ckm_name_to_value = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
if ((ckm_value_to_name = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
|
|
#define ExportConstant(constant) \
|
|
if (_AddIntConstantWithLookup(m, #constant, constant, \
|
|
"CKM_", ckm_name_to_value, ckm_value_to_name) < 0) return;
|
|
|
|
ExportConstant(CKM_RSA_PKCS_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_RSA_PKCS);
|
|
ExportConstant(CKM_RSA_9796);
|
|
ExportConstant(CKM_RSA_X_509);
|
|
|
|
/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
|
|
* are new for v2.0. They are mechanisms which hash and sign */
|
|
ExportConstant(CKM_MD2_RSA_PKCS);
|
|
ExportConstant(CKM_MD5_RSA_PKCS);
|
|
ExportConstant(CKM_SHA1_RSA_PKCS);
|
|
|
|
/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
|
|
* CKM_RSA_PKCS_OAEP are new for v2.10 */
|
|
ExportConstant(CKM_RIPEMD128_RSA_PKCS);
|
|
ExportConstant(CKM_RIPEMD160_RSA_PKCS);
|
|
ExportConstant(CKM_RSA_PKCS_OAEP);
|
|
|
|
/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
|
|
* CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
|
|
ExportConstant(CKM_RSA_X9_31_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_RSA_X9_31);
|
|
ExportConstant(CKM_SHA1_RSA_X9_31);
|
|
ExportConstant(CKM_RSA_PKCS_PSS);
|
|
ExportConstant(CKM_SHA1_RSA_PKCS_PSS);
|
|
|
|
ExportConstant(CKM_DSA_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_DSA);
|
|
ExportConstant(CKM_DSA_SHA1);
|
|
ExportConstant(CKM_DH_PKCS_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_DH_PKCS_DERIVE);
|
|
|
|
/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
|
|
* CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
|
|
* v2.11 */
|
|
ExportConstant(CKM_X9_42_DH_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_X9_42_DH_DERIVE);
|
|
ExportConstant(CKM_X9_42_DH_HYBRID_DERIVE);
|
|
ExportConstant(CKM_X9_42_MQV_DERIVE);
|
|
|
|
/* CKM_SHA256/384/512 are new for v2.20 */
|
|
ExportConstant(CKM_SHA256_RSA_PKCS);
|
|
ExportConstant(CKM_SHA384_RSA_PKCS);
|
|
ExportConstant(CKM_SHA512_RSA_PKCS);
|
|
ExportConstant(CKM_SHA256_RSA_PKCS_PSS);
|
|
ExportConstant(CKM_SHA384_RSA_PKCS_PSS);
|
|
ExportConstant(CKM_SHA512_RSA_PKCS_PSS);
|
|
|
|
/* CKM_SHA224 new for v2.20 amendment 3 */
|
|
ExportConstant(CKM_SHA224_RSA_PKCS);
|
|
ExportConstant(CKM_SHA224_RSA_PKCS_PSS);
|
|
|
|
ExportConstant(CKM_RC2_KEY_GEN);
|
|
ExportConstant(CKM_RC2_ECB);
|
|
ExportConstant(CKM_RC2_CBC);
|
|
ExportConstant(CKM_RC2_MAC);
|
|
|
|
/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
|
|
ExportConstant(CKM_RC2_MAC_GENERAL);
|
|
ExportConstant(CKM_RC2_CBC_PAD);
|
|
|
|
ExportConstant(CKM_RC4_KEY_GEN);
|
|
ExportConstant(CKM_RC4);
|
|
ExportConstant(CKM_DES_KEY_GEN);
|
|
ExportConstant(CKM_DES_ECB);
|
|
ExportConstant(CKM_DES_CBC);
|
|
ExportConstant(CKM_DES_MAC);
|
|
|
|
/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
|
|
ExportConstant(CKM_DES_MAC_GENERAL);
|
|
ExportConstant(CKM_DES_CBC_PAD);
|
|
|
|
ExportConstant(CKM_DES2_KEY_GEN);
|
|
ExportConstant(CKM_DES3_KEY_GEN);
|
|
ExportConstant(CKM_DES3_ECB);
|
|
ExportConstant(CKM_DES3_CBC);
|
|
ExportConstant(CKM_DES3_MAC);
|
|
|
|
/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
|
|
* CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
|
|
* CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
|
|
ExportConstant(CKM_DES3_MAC_GENERAL);
|
|
ExportConstant(CKM_DES3_CBC_PAD);
|
|
ExportConstant(CKM_CDMF_KEY_GEN);
|
|
ExportConstant(CKM_CDMF_ECB);
|
|
ExportConstant(CKM_CDMF_CBC);
|
|
ExportConstant(CKM_CDMF_MAC);
|
|
ExportConstant(CKM_CDMF_MAC_GENERAL);
|
|
ExportConstant(CKM_CDMF_CBC_PAD);
|
|
|
|
/* the following four DES mechanisms are new for v2.20 */
|
|
ExportConstant(CKM_DES_OFB64);
|
|
ExportConstant(CKM_DES_OFB8);
|
|
ExportConstant(CKM_DES_CFB64);
|
|
ExportConstant(CKM_DES_CFB8);
|
|
|
|
ExportConstant(CKM_MD2);
|
|
|
|
/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
|
|
ExportConstant(CKM_MD2_HMAC);
|
|
ExportConstant(CKM_MD2_HMAC_GENERAL);
|
|
|
|
ExportConstant(CKM_MD5);
|
|
|
|
/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
|
|
ExportConstant(CKM_MD5_HMAC);
|
|
ExportConstant(CKM_MD5_HMAC_GENERAL);
|
|
|
|
ExportConstant(CKM_SHA_1);
|
|
|
|
/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
|
|
ExportConstant(CKM_SHA_1_HMAC);
|
|
ExportConstant(CKM_SHA_1_HMAC_GENERAL);
|
|
|
|
/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
|
|
* CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
|
|
* and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
|
|
ExportConstant(CKM_RIPEMD128);
|
|
ExportConstant(CKM_RIPEMD128_HMAC);
|
|
ExportConstant(CKM_RIPEMD128_HMAC_GENERAL);
|
|
ExportConstant(CKM_RIPEMD160);
|
|
ExportConstant(CKM_RIPEMD160_HMAC);
|
|
ExportConstant(CKM_RIPEMD160_HMAC_GENERAL);
|
|
|
|
/* CKM_SHA256/384/512 are new for v2.20 */
|
|
ExportConstant(CKM_SHA256);
|
|
ExportConstant(CKM_SHA256_HMAC);
|
|
ExportConstant(CKM_SHA256_HMAC_GENERAL);
|
|
ExportConstant(CKM_SHA384);
|
|
ExportConstant(CKM_SHA384_HMAC);
|
|
ExportConstant(CKM_SHA384_HMAC_GENERAL);
|
|
ExportConstant(CKM_SHA512);
|
|
ExportConstant(CKM_SHA512_HMAC);
|
|
ExportConstant(CKM_SHA512_HMAC_GENERAL);
|
|
|
|
/* CKM_SHA224 new for v2.20 amendment 3 */
|
|
ExportConstant(CKM_SHA224);
|
|
ExportConstant(CKM_SHA224_HMAC);
|
|
ExportConstant(CKM_SHA224_HMAC_GENERAL);
|
|
|
|
/* All of the following mechanisms are new for v2.0 */
|
|
/* Note that CAST128 and CAST5 are the same algorithm */
|
|
ExportConstant(CKM_CAST_KEY_GEN);
|
|
ExportConstant(CKM_CAST_ECB);
|
|
ExportConstant(CKM_CAST_CBC);
|
|
ExportConstant(CKM_CAST_MAC);
|
|
ExportConstant(CKM_CAST_MAC_GENERAL);
|
|
ExportConstant(CKM_CAST_CBC_PAD);
|
|
ExportConstant(CKM_CAST3_KEY_GEN);
|
|
ExportConstant(CKM_CAST3_ECB);
|
|
ExportConstant(CKM_CAST3_CBC);
|
|
ExportConstant(CKM_CAST3_MAC);
|
|
ExportConstant(CKM_CAST3_MAC_GENERAL);
|
|
ExportConstant(CKM_CAST3_CBC_PAD);
|
|
ExportConstant(CKM_CAST5_KEY_GEN);
|
|
ExportConstant(CKM_CAST128_KEY_GEN);
|
|
ExportConstant(CKM_CAST5_ECB);
|
|
ExportConstant(CKM_CAST128_ECB);
|
|
ExportConstant(CKM_CAST5_CBC);
|
|
ExportConstant(CKM_CAST128_CBC);
|
|
ExportConstant(CKM_CAST5_MAC);
|
|
ExportConstant(CKM_CAST128_MAC);
|
|
ExportConstant(CKM_CAST5_MAC_GENERAL);
|
|
ExportConstant(CKM_CAST128_MAC_GENERAL);
|
|
ExportConstant(CKM_CAST5_CBC_PAD);
|
|
ExportConstant(CKM_CAST128_CBC_PAD);
|
|
ExportConstant(CKM_RC5_KEY_GEN);
|
|
ExportConstant(CKM_RC5_ECB);
|
|
ExportConstant(CKM_RC5_CBC);
|
|
ExportConstant(CKM_RC5_MAC);
|
|
ExportConstant(CKM_RC5_MAC_GENERAL);
|
|
ExportConstant(CKM_RC5_CBC_PAD);
|
|
ExportConstant(CKM_IDEA_KEY_GEN);
|
|
ExportConstant(CKM_IDEA_ECB);
|
|
ExportConstant(CKM_IDEA_CBC);
|
|
ExportConstant(CKM_IDEA_MAC);
|
|
ExportConstant(CKM_IDEA_MAC_GENERAL);
|
|
ExportConstant(CKM_IDEA_CBC_PAD);
|
|
ExportConstant(CKM_GENERIC_SECRET_KEY_GEN);
|
|
ExportConstant(CKM_CONCATENATE_BASE_AND_KEY);
|
|
ExportConstant(CKM_CONCATENATE_BASE_AND_DATA);
|
|
ExportConstant(CKM_CONCATENATE_DATA_AND_BASE);
|
|
ExportConstant(CKM_XOR_BASE_AND_DATA);
|
|
ExportConstant(CKM_EXTRACT_KEY_FROM_KEY);
|
|
ExportConstant(CKM_SSL3_PRE_MASTER_KEY_GEN);
|
|
ExportConstant(CKM_SSL3_MASTER_KEY_DERIVE);
|
|
ExportConstant(CKM_SSL3_KEY_AND_MAC_DERIVE);
|
|
|
|
/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
|
|
* CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
|
|
* CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
|
|
ExportConstant(CKM_SSL3_MASTER_KEY_DERIVE_DH);
|
|
ExportConstant(CKM_TLS_PRE_MASTER_KEY_GEN);
|
|
ExportConstant(CKM_TLS_MASTER_KEY_DERIVE);
|
|
ExportConstant(CKM_TLS_KEY_AND_MAC_DERIVE);
|
|
ExportConstant(CKM_TLS_MASTER_KEY_DERIVE_DH);
|
|
|
|
/* CKM_TLS_PRF is new for v2.20 */
|
|
ExportConstant(CKM_TLS_PRF);
|
|
|
|
ExportConstant(CKM_SSL3_MD5_MAC);
|
|
ExportConstant(CKM_SSL3_SHA1_MAC);
|
|
ExportConstant(CKM_MD5_KEY_DERIVATION);
|
|
ExportConstant(CKM_MD2_KEY_DERIVATION);
|
|
ExportConstant(CKM_SHA1_KEY_DERIVATION);
|
|
|
|
/* CKM_SHA256/384/512 are new for v2.20 */
|
|
ExportConstant(CKM_SHA256_KEY_DERIVATION);
|
|
ExportConstant(CKM_SHA384_KEY_DERIVATION);
|
|
ExportConstant(CKM_SHA512_KEY_DERIVATION);
|
|
|
|
/* CKM_SHA224 new for v2.20 amendment 3 */
|
|
ExportConstant(CKM_SHA224_KEY_DERIVATION);
|
|
|
|
ExportConstant(CKM_PBE_MD2_DES_CBC);
|
|
ExportConstant(CKM_PBE_MD5_DES_CBC);
|
|
ExportConstant(CKM_PBE_MD5_CAST_CBC);
|
|
ExportConstant(CKM_PBE_MD5_CAST3_CBC);
|
|
ExportConstant(CKM_PBE_MD5_CAST5_CBC);
|
|
ExportConstant(CKM_PBE_MD5_CAST128_CBC);
|
|
ExportConstant(CKM_PBE_SHA1_CAST5_CBC);
|
|
ExportConstant(CKM_PBE_SHA1_CAST128_CBC);
|
|
ExportConstant(CKM_PBE_SHA1_RC4_128);
|
|
ExportConstant(CKM_PBE_SHA1_RC4_40);
|
|
ExportConstant(CKM_PBE_SHA1_DES3_EDE_CBC);
|
|
ExportConstant(CKM_PBE_SHA1_DES2_EDE_CBC);
|
|
ExportConstant(CKM_PBE_SHA1_RC2_128_CBC);
|
|
ExportConstant(CKM_PBE_SHA1_RC2_40_CBC);
|
|
|
|
/* CKM_PKCS5_PBKD2 is new for v2.10 */
|
|
ExportConstant(CKM_PKCS5_PBKD2);
|
|
|
|
ExportConstant(CKM_PBA_SHA1_WITH_SHA1_HMAC);
|
|
|
|
/* WTLS mechanisms are new for v2.20 */
|
|
ExportConstant(CKM_WTLS_PRE_MASTER_KEY_GEN);
|
|
ExportConstant(CKM_WTLS_MASTER_KEY_DERIVE);
|
|
ExportConstant(CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC);
|
|
ExportConstant(CKM_WTLS_PRF);
|
|
ExportConstant(CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE);
|
|
ExportConstant(CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE);
|
|
|
|
ExportConstant(CKM_KEY_WRAP_LYNKS);
|
|
ExportConstant(CKM_KEY_WRAP_SET_OAEP);
|
|
|
|
/* CKM_CMS_SIG is new for v2.20 */
|
|
ExportConstant(CKM_CMS_SIG);
|
|
|
|
/* Fortezza mechanisms */
|
|
ExportConstant(CKM_SKIPJACK_KEY_GEN);
|
|
ExportConstant(CKM_SKIPJACK_ECB64);
|
|
ExportConstant(CKM_SKIPJACK_CBC64);
|
|
ExportConstant(CKM_SKIPJACK_OFB64);
|
|
ExportConstant(CKM_SKIPJACK_CFB64);
|
|
ExportConstant(CKM_SKIPJACK_CFB32);
|
|
ExportConstant(CKM_SKIPJACK_CFB16);
|
|
ExportConstant(CKM_SKIPJACK_CFB8);
|
|
ExportConstant(CKM_SKIPJACK_WRAP);
|
|
ExportConstant(CKM_SKIPJACK_PRIVATE_WRAP);
|
|
ExportConstant(CKM_SKIPJACK_RELAYX);
|
|
ExportConstant(CKM_KEA_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_KEA_KEY_DERIVE);
|
|
ExportConstant(CKM_FORTEZZA_TIMESTAMP);
|
|
ExportConstant(CKM_BATON_KEY_GEN);
|
|
ExportConstant(CKM_BATON_ECB128);
|
|
ExportConstant(CKM_BATON_ECB96);
|
|
ExportConstant(CKM_BATON_CBC128);
|
|
ExportConstant(CKM_BATON_COUNTER);
|
|
ExportConstant(CKM_BATON_SHUFFLE);
|
|
ExportConstant(CKM_BATON_WRAP);
|
|
|
|
/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
|
|
* CKM_EC_KEY_PAIR_GEN is preferred */
|
|
ExportConstant(CKM_ECDSA_KEY_PAIR_GEN);
|
|
ExportConstant(CKM_EC_KEY_PAIR_GEN);
|
|
|
|
ExportConstant(CKM_ECDSA);
|
|
ExportConstant(CKM_ECDSA_SHA1);
|
|
|
|
/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
|
|
* are new for v2.11 */
|
|
ExportConstant(CKM_ECDH1_DERIVE);
|
|
ExportConstant(CKM_ECDH1_COFACTOR_DERIVE);
|
|
ExportConstant(CKM_ECMQV_DERIVE);
|
|
|
|
ExportConstant(CKM_JUNIPER_KEY_GEN);
|
|
ExportConstant(CKM_JUNIPER_ECB128);
|
|
ExportConstant(CKM_JUNIPER_CBC128);
|
|
ExportConstant(CKM_JUNIPER_COUNTER);
|
|
ExportConstant(CKM_JUNIPER_SHUFFLE);
|
|
ExportConstant(CKM_JUNIPER_WRAP);
|
|
ExportConstant(CKM_FASTHASH);
|
|
|
|
/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
|
|
* CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
|
|
* CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
|
|
* new for v2.11 */
|
|
ExportConstant(CKM_AES_KEY_GEN);
|
|
ExportConstant(CKM_AES_ECB);
|
|
ExportConstant(CKM_AES_CBC);
|
|
ExportConstant(CKM_AES_MAC);
|
|
ExportConstant(CKM_AES_MAC_GENERAL);
|
|
ExportConstant(CKM_AES_CBC_PAD);
|
|
|
|
/* BlowFish and TwoFish are new for v2.20 */
|
|
ExportConstant(CKM_BLOWFISH_KEY_GEN);
|
|
ExportConstant(CKM_BLOWFISH_CBC);
|
|
ExportConstant(CKM_TWOFISH_KEY_GEN);
|
|
ExportConstant(CKM_TWOFISH_CBC);
|
|
|
|
/* Camellia is proposed for v2.20 Amendment 3 */
|
|
ExportConstant(CKM_CAMELLIA_KEY_GEN);
|
|
ExportConstant(CKM_CAMELLIA_ECB);
|
|
ExportConstant(CKM_CAMELLIA_CBC);
|
|
ExportConstant(CKM_CAMELLIA_MAC);
|
|
ExportConstant(CKM_CAMELLIA_MAC_GENERAL);
|
|
ExportConstant(CKM_CAMELLIA_CBC_PAD);
|
|
ExportConstant(CKM_CAMELLIA_ECB_ENCRYPT_DATA);
|
|
ExportConstant(CKM_CAMELLIA_CBC_ENCRYPT_DATA);
|
|
|
|
#if defined(CKM_SEED_KEY_GEN)
|
|
ExportConstant(CKM_SEED_KEY_GEN);
|
|
ExportConstant(CKM_SEED_ECB);
|
|
ExportConstant(CKM_SEED_CBC);
|
|
ExportConstant(CKM_SEED_MAC);
|
|
ExportConstant(CKM_SEED_MAC_GENERAL);
|
|
ExportConstant(CKM_SEED_CBC_PAD);
|
|
ExportConstant(CKM_SEED_ECB_ENCRYPT_DATA);
|
|
ExportConstant(CKM_SEED_CBC_ENCRYPT_DATA);
|
|
#endif
|
|
|
|
/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
|
|
ExportConstant(CKM_DES_ECB_ENCRYPT_DATA);
|
|
ExportConstant(CKM_DES_CBC_ENCRYPT_DATA);
|
|
ExportConstant(CKM_DES3_ECB_ENCRYPT_DATA);
|
|
ExportConstant(CKM_DES3_CBC_ENCRYPT_DATA);
|
|
ExportConstant(CKM_AES_ECB_ENCRYPT_DATA);
|
|
ExportConstant(CKM_AES_CBC_ENCRYPT_DATA);
|
|
|
|
ExportConstant(CKM_DSA_PARAMETER_GEN);
|
|
ExportConstant(CKM_DH_PKCS_PARAMETER_GEN);
|
|
ExportConstant(CKM_X9_42_DH_PARAMETER_GEN);
|
|
|
|
#undef ExportConstant
|
|
|
|
/***************************************************************************
|
|
* Attribute Types
|
|
***************************************************************************/
|
|
if ((cka_name_to_value = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
if ((cka_value_to_name = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
|
|
#define ExportConstant(constant) \
|
|
if (_AddIntConstantWithLookup(m, #constant, constant, \
|
|
"CKA_", cka_name_to_value, cka_value_to_name) < 0) return;
|
|
|
|
/* The following attribute types are defined: */
|
|
ExportConstant(CKA_CLASS);
|
|
ExportConstant(CKA_TOKEN);
|
|
ExportConstant(CKA_PRIVATE);
|
|
ExportConstant(CKA_LABEL);
|
|
ExportConstant(CKA_APPLICATION);
|
|
ExportConstant(CKA_VALUE);
|
|
|
|
/* CKA_OBJECT_ID is new for v2.10 */
|
|
ExportConstant(CKA_OBJECT_ID);
|
|
|
|
ExportConstant(CKA_CERTIFICATE_TYPE);
|
|
ExportConstant(CKA_ISSUER);
|
|
ExportConstant(CKA_SERIAL_NUMBER);
|
|
|
|
/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new for v2.10 */
|
|
ExportConstant(CKA_AC_ISSUER);
|
|
ExportConstant(CKA_OWNER);
|
|
ExportConstant(CKA_ATTR_TYPES);
|
|
|
|
/* CKA_TRUSTED is new for v2.11 */
|
|
ExportConstant(CKA_TRUSTED);
|
|
|
|
/* CKA_CERTIFICATE_CATEGORY ...
|
|
* CKA_CHECK_VALUE are new for v2.20 */
|
|
ExportConstant(CKA_CERTIFICATE_CATEGORY);
|
|
ExportConstant(CKA_JAVA_MIDP_SECURITY_DOMAIN);
|
|
ExportConstant(CKA_URL);
|
|
ExportConstant(CKA_HASH_OF_SUBJECT_PUBLIC_KEY);
|
|
ExportConstant(CKA_HASH_OF_ISSUER_PUBLIC_KEY);
|
|
ExportConstant(CKA_CHECK_VALUE);
|
|
|
|
ExportConstant(CKA_KEY_TYPE);
|
|
ExportConstant(CKA_SUBJECT);
|
|
ExportConstant(CKA_ID);
|
|
ExportConstant(CKA_SENSITIVE);
|
|
ExportConstant(CKA_ENCRYPT);
|
|
ExportConstant(CKA_DECRYPT);
|
|
ExportConstant(CKA_WRAP);
|
|
ExportConstant(CKA_UNWRAP);
|
|
ExportConstant(CKA_SIGN);
|
|
ExportConstant(CKA_SIGN_RECOVER);
|
|
ExportConstant(CKA_VERIFY);
|
|
ExportConstant(CKA_VERIFY_RECOVER);
|
|
ExportConstant(CKA_DERIVE);
|
|
ExportConstant(CKA_START_DATE);
|
|
ExportConstant(CKA_END_DATE);
|
|
ExportConstant(CKA_MODULUS);
|
|
ExportConstant(CKA_MODULUS_BITS);
|
|
ExportConstant(CKA_PUBLIC_EXPONENT);
|
|
ExportConstant(CKA_PRIVATE_EXPONENT);
|
|
ExportConstant(CKA_PRIME_1);
|
|
ExportConstant(CKA_PRIME_2);
|
|
ExportConstant(CKA_EXPONENT_1);
|
|
ExportConstant(CKA_EXPONENT_2);
|
|
ExportConstant(CKA_COEFFICIENT);
|
|
ExportConstant(CKA_PRIME);
|
|
ExportConstant(CKA_SUBPRIME);
|
|
ExportConstant(CKA_BASE);
|
|
|
|
/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
|
|
ExportConstant(CKA_PRIME_BITS);
|
|
ExportConstant(CKA_SUBPRIME_BITS);
|
|
ExportConstant(CKA_SUB_PRIME_BITS);
|
|
/* (To retain backwards-compatibility) */
|
|
|
|
ExportConstant(CKA_VALUE_BITS);
|
|
ExportConstant(CKA_VALUE_LEN);
|
|
|
|
/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
|
|
* CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
|
|
* and CKA_EC_POINT are new for v2.0 */
|
|
ExportConstant(CKA_EXTRACTABLE);
|
|
ExportConstant(CKA_LOCAL);
|
|
ExportConstant(CKA_NEVER_EXTRACTABLE);
|
|
ExportConstant(CKA_ALWAYS_SENSITIVE);
|
|
|
|
/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
|
|
ExportConstant(CKA_KEY_GEN_MECHANISM);
|
|
|
|
ExportConstant(CKA_MODIFIABLE);
|
|
|
|
/* CKA_ECDSA_PARAMS is deprecated in v2.11,
|
|
* CKA_EC_PARAMS is preferred. */
|
|
ExportConstant(CKA_ECDSA_PARAMS);
|
|
ExportConstant(CKA_EC_PARAMS);
|
|
|
|
ExportConstant(CKA_EC_POINT);
|
|
|
|
/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
|
|
* are new for v2.10. Deprecated in v2.11 and onwards. */
|
|
ExportConstant(CKA_SECONDARY_AUTH);
|
|
ExportConstant(CKA_AUTH_PIN_FLAGS);
|
|
|
|
/* CKA_ALWAYS_AUTHENTICATE ...
|
|
* CKA_UNWRAP_TEMPLATE are new for v2.20 */
|
|
ExportConstant(CKA_ALWAYS_AUTHENTICATE);
|
|
|
|
ExportConstant(CKA_WRAP_WITH_TRUSTED);
|
|
ExportConstant(CKA_WRAP_TEMPLATE);
|
|
ExportConstant(CKA_UNWRAP_TEMPLATE);
|
|
|
|
/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
|
|
* are new for v2.10 */
|
|
ExportConstant(CKA_HW_FEATURE_TYPE);
|
|
ExportConstant(CKA_RESET_ON_INIT);
|
|
ExportConstant(CKA_HAS_RESET);
|
|
|
|
/* The following attributes are new for v2.20 */
|
|
ExportConstant(CKA_PIXEL_X);
|
|
ExportConstant(CKA_PIXEL_Y);
|
|
ExportConstant(CKA_RESOLUTION);
|
|
ExportConstant(CKA_CHAR_ROWS);
|
|
ExportConstant(CKA_CHAR_COLUMNS);
|
|
ExportConstant(CKA_COLOR);
|
|
ExportConstant(CKA_BITS_PER_PIXEL);
|
|
ExportConstant(CKA_CHAR_SETS);
|
|
ExportConstant(CKA_ENCODING_METHODS);
|
|
ExportConstant(CKA_MIME_TYPES);
|
|
ExportConstant(CKA_MECHANISM_TYPE);
|
|
ExportConstant(CKA_REQUIRED_CMS_ATTRIBUTES);
|
|
ExportConstant(CKA_DEFAULT_CMS_ATTRIBUTES);
|
|
ExportConstant(CKA_SUPPORTED_CMS_ATTRIBUTES);
|
|
ExportConstant(CKA_ALLOWED_MECHANISMS);
|
|
|
|
ExportConstant(CKA_VENDOR_DEFINED);
|
|
|
|
#undef ExportConstant
|
|
|
|
/***************************************************************************
|
|
* SEC OID TAGS
|
|
***************************************************************************/
|
|
|
|
if ((sec_oid_name_to_value = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
if ((sec_oid_value_to_name = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
|
|
#define ExportConstant(constant) \
|
|
if (_AddIntConstantWithLookup(m, #constant, constant, \
|
|
"SEC_OID_", sec_oid_name_to_value, sec_oid_value_to_name) < 0) return;
|
|
|
|
ExportConstant(SEC_OID_UNKNOWN);
|
|
ExportConstant(SEC_OID_MD2);
|
|
ExportConstant(SEC_OID_MD4);
|
|
ExportConstant(SEC_OID_MD5);
|
|
ExportConstant(SEC_OID_SHA1);
|
|
ExportConstant(SEC_OID_RC2_CBC);
|
|
ExportConstant(SEC_OID_RC4);
|
|
ExportConstant(SEC_OID_DES_EDE3_CBC);
|
|
ExportConstant(SEC_OID_RC5_CBC_PAD);
|
|
ExportConstant(SEC_OID_DES_ECB);
|
|
ExportConstant(SEC_OID_DES_CBC);
|
|
ExportConstant(SEC_OID_DES_OFB);
|
|
ExportConstant(SEC_OID_DES_CFB);
|
|
ExportConstant(SEC_OID_DES_MAC);
|
|
ExportConstant(SEC_OID_DES_EDE);
|
|
ExportConstant(SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE);
|
|
ExportConstant(SEC_OID_PKCS1_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC);
|
|
ExportConstant(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC);
|
|
ExportConstant(SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC);
|
|
ExportConstant(SEC_OID_PKCS7);
|
|
ExportConstant(SEC_OID_PKCS7_DATA);
|
|
ExportConstant(SEC_OID_PKCS7_SIGNED_DATA);
|
|
ExportConstant(SEC_OID_PKCS7_ENVELOPED_DATA);
|
|
ExportConstant(SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA);
|
|
ExportConstant(SEC_OID_PKCS7_DIGESTED_DATA);
|
|
ExportConstant(SEC_OID_PKCS7_ENCRYPTED_DATA);
|
|
ExportConstant(SEC_OID_PKCS9_EMAIL_ADDRESS);
|
|
ExportConstant(SEC_OID_PKCS9_UNSTRUCTURED_NAME);
|
|
ExportConstant(SEC_OID_PKCS9_CONTENT_TYPE);
|
|
ExportConstant(SEC_OID_PKCS9_MESSAGE_DIGEST);
|
|
ExportConstant(SEC_OID_PKCS9_SIGNING_TIME);
|
|
ExportConstant(SEC_OID_PKCS9_COUNTER_SIGNATURE);
|
|
ExportConstant(SEC_OID_PKCS9_CHALLENGE_PASSWORD);
|
|
ExportConstant(SEC_OID_PKCS9_UNSTRUCTURED_ADDRESS);
|
|
ExportConstant(SEC_OID_PKCS9_EXTENDED_CERTIFICATE_ATTRIBUTES);
|
|
ExportConstant(SEC_OID_PKCS9_SMIME_CAPABILITIES);
|
|
ExportConstant(SEC_OID_AVA_COMMON_NAME);
|
|
ExportConstant(SEC_OID_AVA_COUNTRY_NAME);
|
|
ExportConstant(SEC_OID_AVA_LOCALITY);
|
|
ExportConstant(SEC_OID_AVA_STATE_OR_PROVINCE);
|
|
ExportConstant(SEC_OID_AVA_ORGANIZATION_NAME);
|
|
ExportConstant(SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME);
|
|
ExportConstant(SEC_OID_AVA_DN_QUALIFIER);
|
|
ExportConstant(SEC_OID_AVA_DC);
|
|
|
|
ExportConstant(SEC_OID_NS_TYPE_GIF);
|
|
ExportConstant(SEC_OID_NS_TYPE_JPEG);
|
|
ExportConstant(SEC_OID_NS_TYPE_URL);
|
|
ExportConstant(SEC_OID_NS_TYPE_HTML);
|
|
ExportConstant(SEC_OID_NS_TYPE_CERT_SEQUENCE);
|
|
ExportConstant(SEC_OID_MISSI_KEA_DSS_OLD);
|
|
ExportConstant(SEC_OID_MISSI_DSS_OLD);
|
|
ExportConstant(SEC_OID_MISSI_KEA_DSS);
|
|
ExportConstant(SEC_OID_MISSI_DSS);
|
|
ExportConstant(SEC_OID_MISSI_KEA);
|
|
ExportConstant(SEC_OID_MISSI_ALT_KEA);
|
|
|
|
/* Netscape private certificate extensions */
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_NETSCAPE_OK);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_ISSUER_LOGO);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_SUBJECT_LOGO);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CERT_TYPE);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_BASE_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_REVOCATION_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CA_CRL_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CA_CERT_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CA_POLICY_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_HOMEPAGE_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_ENTITY_LOGO);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_USER_PICTURE);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_COMMENT);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME);
|
|
ExportConstant(SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
|
|
|
|
/* x.509 v3 Extensions */
|
|
ExportConstant(SEC_OID_X509_SUBJECT_DIRECTORY_ATTR);
|
|
ExportConstant(SEC_OID_X509_SUBJECT_KEY_ID);
|
|
ExportConstant(SEC_OID_X509_KEY_USAGE);
|
|
ExportConstant(SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD);
|
|
ExportConstant(SEC_OID_X509_SUBJECT_ALT_NAME);
|
|
ExportConstant(SEC_OID_X509_ISSUER_ALT_NAME);
|
|
ExportConstant(SEC_OID_X509_BASIC_CONSTRAINTS);
|
|
ExportConstant(SEC_OID_X509_NAME_CONSTRAINTS);
|
|
ExportConstant(SEC_OID_X509_CRL_DIST_POINTS);
|
|
ExportConstant(SEC_OID_X509_CERTIFICATE_POLICIES);
|
|
ExportConstant(SEC_OID_X509_POLICY_MAPPINGS);
|
|
ExportConstant(SEC_OID_X509_POLICY_CONSTRAINTS);
|
|
ExportConstant(SEC_OID_X509_AUTH_KEY_ID);
|
|
ExportConstant(SEC_OID_X509_EXT_KEY_USAGE);
|
|
ExportConstant(SEC_OID_X509_AUTH_INFO_ACCESS);
|
|
|
|
ExportConstant(SEC_OID_X509_CRL_NUMBER);
|
|
ExportConstant(SEC_OID_X509_REASON_CODE);
|
|
ExportConstant(SEC_OID_X509_INVALID_DATE);
|
|
/* End of x.509 v3 Extensions */
|
|
|
|
ExportConstant(SEC_OID_X500_RSA_ENCRYPTION);
|
|
|
|
/* alg 1485 additions */
|
|
ExportConstant(SEC_OID_RFC1274_UID);
|
|
ExportConstant(SEC_OID_RFC1274_MAIL);
|
|
|
|
/* PKCS 12 additions */
|
|
ExportConstant(SEC_OID_PKCS12);
|
|
ExportConstant(SEC_OID_PKCS12_MODE_IDS);
|
|
ExportConstant(SEC_OID_PKCS12_ESPVK_IDS);
|
|
ExportConstant(SEC_OID_PKCS12_BAG_IDS);
|
|
ExportConstant(SEC_OID_PKCS12_CERT_BAG_IDS);
|
|
ExportConstant(SEC_OID_PKCS12_OIDS);
|
|
ExportConstant(SEC_OID_PKCS12_PBE_IDS);
|
|
ExportConstant(SEC_OID_PKCS12_SIGNATURE_IDS);
|
|
ExportConstant(SEC_OID_PKCS12_ENVELOPING_IDS);
|
|
/* SEC_OID_PKCS12_OFFLINE_TRANSPORT_MODE,
|
|
SEC_OID_PKCS12_ONLINE_TRANSPORT_MODE, */
|
|
ExportConstant(SEC_OID_PKCS12_PKCS8_KEY_SHROUDING);
|
|
ExportConstant(SEC_OID_PKCS12_KEY_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_SECRET_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_X509_CERT_CRL_BAG);
|
|
ExportConstant(SEC_OID_PKCS12_SDSI_CERT_BAG);
|
|
ExportConstant(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4);
|
|
ExportConstant(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4);
|
|
ExportConstant(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_128_BIT_RC4);
|
|
ExportConstant(SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_40_BIT_RC4);
|
|
ExportConstant(SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_TRIPLE_DES);
|
|
ExportConstant(SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST);
|
|
/* end of PKCS 12 additions */
|
|
|
|
/* DSA signatures */
|
|
ExportConstant(SEC_OID_ANSIX9_DSA_SIGNATURE);
|
|
ExportConstant(SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST);
|
|
ExportConstant(SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST);
|
|
|
|
/* Verisign OIDs */
|
|
ExportConstant(SEC_OID_VERISIGN_USER_NOTICES);
|
|
|
|
/* PKIX OIDs */
|
|
ExportConstant(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
|
|
ExportConstant(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
|
|
ExportConstant(SEC_OID_PKIX_OCSP);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_NONCE);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_CRL);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_RESPONSE);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_NO_CHECK);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF);
|
|
ExportConstant(SEC_OID_PKIX_OCSP_SERVICE_LOCATOR);
|
|
ExportConstant(SEC_OID_PKIX_REGCTRL_REGTOKEN);
|
|
ExportConstant(SEC_OID_PKIX_REGCTRL_AUTHENTICATOR);
|
|
ExportConstant(SEC_OID_PKIX_REGCTRL_PKIPUBINFO);
|
|
ExportConstant(SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS);
|
|
ExportConstant(SEC_OID_PKIX_REGCTRL_OLD_CERT_ID);
|
|
ExportConstant(SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY);
|
|
ExportConstant(SEC_OID_PKIX_REGINFO_UTF8_PAIRS);
|
|
ExportConstant(SEC_OID_PKIX_REGINFO_CERT_REQUEST);
|
|
ExportConstant(SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
|
|
ExportConstant(SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
|
|
ExportConstant(SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
|
|
ExportConstant(SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
|
|
ExportConstant(SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
|
|
ExportConstant(SEC_OID_OCSP_RESPONDER);
|
|
|
|
/* Netscape Algorithm OIDs */
|
|
ExportConstant(SEC_OID_NETSCAPE_SMIME_KEA);
|
|
|
|
/* Skipjack OID -- ### mwelch temporary */
|
|
ExportConstant(SEC_OID_FORTEZZA_SKIPJACK);
|
|
|
|
/* PKCS 12 V2 oids */
|
|
ExportConstant(SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4);
|
|
ExportConstant(SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4);
|
|
ExportConstant(SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
|
|
ExportConstant(SEC_OID_PKCS12_SAFE_CONTENTS_ID);
|
|
ExportConstant(SEC_OID_PKCS12_PKCS8_SHROUDED_KEY_BAG_ID);
|
|
|
|
ExportConstant(SEC_OID_PKCS12_V1_KEY_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_V1_CERT_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_V1_CRL_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_V1_SECRET_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID);
|
|
ExportConstant(SEC_OID_PKCS9_X509_CERT);
|
|
ExportConstant(SEC_OID_PKCS9_SDSI_CERT);
|
|
ExportConstant(SEC_OID_PKCS9_X509_CRL);
|
|
ExportConstant(SEC_OID_PKCS9_FRIENDLY_NAME);
|
|
ExportConstant(SEC_OID_PKCS9_LOCAL_KEY_ID);
|
|
ExportConstant(SEC_OID_BOGUS_KEY_USAGE);
|
|
|
|
/*Diffe Helman OIDS */
|
|
ExportConstant(SEC_OID_X942_DIFFIE_HELMAN_KEY);
|
|
|
|
/* Netscape other name types */
|
|
ExportConstant(SEC_OID_NETSCAPE_NICKNAME);
|
|
|
|
/* Cert Server OIDS */
|
|
ExportConstant(SEC_OID_NETSCAPE_RECOVERY_REQUEST);
|
|
|
|
/* New PSM certificate management OIDs */
|
|
ExportConstant(SEC_OID_CERT_RENEWAL_LOCATOR);
|
|
ExportConstant(SEC_OID_NS_CERT_EXT_SCOPE_OF_USE);
|
|
|
|
/* CMS (RFC2630) OIDs */
|
|
ExportConstant(SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN);
|
|
ExportConstant(SEC_OID_CMS_3DES_KEY_WRAP);
|
|
ExportConstant(SEC_OID_CMS_RC2_KEY_WRAP);
|
|
|
|
/* SMIME attributes */
|
|
ExportConstant(SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE);
|
|
|
|
/* AES OIDs */
|
|
ExportConstant(SEC_OID_AES_128_ECB);
|
|
ExportConstant(SEC_OID_AES_128_CBC);
|
|
ExportConstant(SEC_OID_AES_192_ECB);
|
|
ExportConstant(SEC_OID_AES_192_CBC);
|
|
ExportConstant(SEC_OID_AES_256_ECB);
|
|
ExportConstant(SEC_OID_AES_256_CBC);
|
|
|
|
ExportConstant(SEC_OID_SDN702_DSA_SIGNATURE);
|
|
|
|
ExportConstant(SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE);
|
|
|
|
ExportConstant(SEC_OID_SHA256);
|
|
ExportConstant(SEC_OID_SHA384);
|
|
ExportConstant(SEC_OID_SHA512);
|
|
|
|
ExportConstant(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION);
|
|
ExportConstant(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION);
|
|
|
|
ExportConstant(SEC_OID_AES_128_KEY_WRAP);
|
|
ExportConstant(SEC_OID_AES_192_KEY_WRAP);
|
|
ExportConstant(SEC_OID_AES_256_KEY_WRAP);
|
|
|
|
/* Elliptic Curve Cryptography (ECC) OIDs */
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PUBLIC_KEY);
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE);
|
|
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST);
|
|
|
|
/* ANSI X9.62 named elliptic curves (prime field) */
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME192V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME192V2);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME192V3);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME239V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME239V2);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME239V3);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_PRIME256V1);
|
|
|
|
/* SECG named elliptic curves (prime field) */
|
|
ExportConstant(SEC_OID_SECG_EC_SECP112R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP112R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP128R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP128R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP160K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP160R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP160R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP192K1);
|
|
/* SEC_OID_SECG_EC_SECP192R1 is SEC_OID_ANSIX962_EC_PRIME192V1 */
|
|
ExportConstant(SEC_OID_SECG_EC_SECP224K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP224R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP256K1);
|
|
/* SEC_OID_SECG_EC_SECP256R1 is SEC_OID_ANSIX962_EC_PRIME256V1 */
|
|
ExportConstant(SEC_OID_SECG_EC_SECP384R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP521R1);
|
|
|
|
/* ANSI X9.62 named elliptic curves (characteristic two field) */
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB163V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB163V2);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB163V3);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB176V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB191V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB191V2);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB191V3);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2ONB191V4);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2ONB191V5);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB208W1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB239V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB239V2);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB239V3);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2ONB239V4);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2ONB239V5);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB272W1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB304W1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB359V1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2PNB368W1);
|
|
ExportConstant(SEC_OID_ANSIX962_EC_C2TNB431R1);
|
|
|
|
/* SECG named elliptic curves (characteristic two field) */
|
|
ExportConstant(SEC_OID_SECG_EC_SECT113R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT113R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT131R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT131R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT163K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT163R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT163R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT193R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT193R2);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT233K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT233R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT239K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT283K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT283R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT409K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT409R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT571K1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECT571R1);
|
|
|
|
ExportConstant(SEC_OID_NETSCAPE_AOLSCREENNAME);
|
|
|
|
ExportConstant(SEC_OID_AVA_SURNAME);
|
|
ExportConstant(SEC_OID_AVA_SERIAL_NUMBER);
|
|
ExportConstant(SEC_OID_AVA_STREET_ADDRESS);
|
|
ExportConstant(SEC_OID_AVA_TITLE);
|
|
ExportConstant(SEC_OID_AVA_POSTAL_ADDRESS);
|
|
ExportConstant(SEC_OID_AVA_POSTAL_CODE);
|
|
ExportConstant(SEC_OID_AVA_POST_OFFICE_BOX);
|
|
ExportConstant(SEC_OID_AVA_GIVEN_NAME);
|
|
ExportConstant(SEC_OID_AVA_INITIALS);
|
|
ExportConstant(SEC_OID_AVA_GENERATION_QUALIFIER);
|
|
ExportConstant(SEC_OID_AVA_HOUSE_IDENTIFIER);
|
|
ExportConstant(SEC_OID_AVA_PSEUDONYM);
|
|
|
|
/* More OIDs */
|
|
ExportConstant(SEC_OID_PKIX_CA_ISSUERS);
|
|
ExportConstant(SEC_OID_PKCS9_EXTENSION_REQUEST);
|
|
|
|
/* new EC Signature oids */
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST);
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST);
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE);
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE);
|
|
ExportConstant(SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE);
|
|
|
|
/* More id-ce and id-pe OIDs from RFC 3280 */
|
|
ExportConstant(SEC_OID_X509_HOLD_INSTRUCTION_CODE);
|
|
ExportConstant(SEC_OID_X509_DELTA_CRL_INDICATOR);
|
|
ExportConstant(SEC_OID_X509_ISSUING_DISTRIBUTION_POINT);
|
|
ExportConstant(SEC_OID_X509_CERT_ISSUER);
|
|
ExportConstant(SEC_OID_X509_FRESHEST_CRL);
|
|
ExportConstant(SEC_OID_X509_INHIBIT_ANY_POLICY);
|
|
ExportConstant(SEC_OID_X509_SUBJECT_INFO_ACCESS);
|
|
|
|
/* Camellia OIDs (RFC3657)*/
|
|
ExportConstant(SEC_OID_CAMELLIA_128_CBC);
|
|
ExportConstant(SEC_OID_CAMELLIA_192_CBC);
|
|
ExportConstant(SEC_OID_CAMELLIA_256_CBC);
|
|
|
|
/* PKCS 5 V2 OIDS */
|
|
ExportConstant(SEC_OID_PKCS5_PBKDF2);
|
|
ExportConstant(SEC_OID_PKCS5_PBES2);
|
|
ExportConstant(SEC_OID_PKCS5_PBMAC1);
|
|
ExportConstant(SEC_OID_HMAC_SHA1);
|
|
ExportConstant(SEC_OID_HMAC_SHA224);
|
|
ExportConstant(SEC_OID_HMAC_SHA256);
|
|
ExportConstant(SEC_OID_HMAC_SHA384);
|
|
ExportConstant(SEC_OID_HMAC_SHA512);
|
|
|
|
ExportConstant(SEC_OID_PKIX_TIMESTAMPING);
|
|
ExportConstant(SEC_OID_PKIX_CA_REPOSITORY);
|
|
|
|
ExportConstant(SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE);
|
|
|
|
#if defined(SEC_OID_SEED_CBC)
|
|
ExportConstant(SEC_OID_SEED_CBC);
|
|
#endif
|
|
|
|
#if defined(SEC_OID_X509_ANY_POLICY)
|
|
ExportConstant(SEC_OID_X509_ANY_POLICY);
|
|
#endif
|
|
|
|
ExportConstant(SEC_OID_SECG_EC_SECP192R1);
|
|
ExportConstant(SEC_OID_SECG_EC_SECP256R1);
|
|
ExportConstant(SEC_OID_PKCS12_KEY_USAGE);
|
|
|
|
#undef ExportConstant
|
|
|
|
/***************************************************************************
|
|
* PK11Origin
|
|
***************************************************************************/
|
|
AddIntConstant(PK11_OriginNULL); /* There is not key, it's a null SymKey */
|
|
AddIntConstant(PK11_OriginDerive); /* Key was derived from some other key */
|
|
AddIntConstant(PK11_OriginGenerated); /* Key was generated (also PBE keys) */
|
|
AddIntConstant(PK11_OriginFortezzaHack); /* Key was marked for fortezza hack */
|
|
AddIntConstant(PK11_OriginUnwrap); /* Key was unwrapped or decrypted */
|
|
|
|
/***************************************************************************
|
|
* PK11 Slot Disabled Reason
|
|
***************************************************************************/
|
|
|
|
AddIntConstant(PK11_DIS_NONE); /* no reason */
|
|
AddIntConstant(PK11_DIS_USER_SELECTED); /* user disabled */
|
|
AddIntConstant(PK11_DIS_COULD_NOT_INIT_TOKEN); /* could not initialize token */
|
|
AddIntConstant(PK11_DIS_TOKEN_VERIFY_FAILED); /* could not verify token */
|
|
AddIntConstant(PK11_DIS_TOKEN_NOT_PRESENT); /* token not present */
|
|
|
|
|
|
/***************************************************************************
|
|
* PKCS12
|
|
***************************************************************************/
|
|
|
|
if ((pkcs12_cipher_name_to_value = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
if ((pkcs12_cipher_value_to_name = PyDict_New()) == NULL) {
|
|
return;
|
|
}
|
|
|
|
#define ExportConstant(constant) \
|
|
if (_AddIntConstantWithLookup(m, #constant, constant, \
|
|
"PKCS12_", pkcs12_cipher_name_to_value, pkcs12_cipher_value_to_name) < 0) return;
|
|
|
|
ExportConstant(PKCS12_RC2_CBC_40);
|
|
ExportConstant(PKCS12_RC2_CBC_128);
|
|
ExportConstant(PKCS12_RC4_40);
|
|
ExportConstant(PKCS12_RC4_128);
|
|
ExportConstant(PKCS12_DES_56);
|
|
ExportConstant(PKCS12_DES_EDE3_168);
|
|
|
|
}
|