blob: 7ad1a145551e464161212716a0b331f39eb83fd8 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509req.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
5 *
6 * X.509 Request handling, mostly thin wrapping.
7 * See the file RATIONALE for a short explanation of why this module was written.
8 */
9#include <Python.h>
10#define crypto_MODULE
11#include "crypto.h"
12
13static char *CVSid = "@(#) $Id: x509req.c,v 1.15 2002/09/04 22:24:59 iko Exp $";
14
15
16static char crypto_X509Req_get_subject_doc[] = "\n\
17Create an X509Name object for the subject of the certificate request\n\
18\n\
19Arguments: self - The X509Req object\n\
20 args - The Python argument tuple, should be empty\n\
21Returns: An X509Name object\n\
22";
23
24static PyObject *
25crypto_X509Req_get_subject(crypto_X509ReqObj *self, PyObject *args)
26{
27 crypto_X509NameObj *crypto_X509Name_New(X509_NAME *, int);
28 X509_NAME *name;
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -050029 crypto_X509NameObj* pyname;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050030
31 if (!PyArg_ParseTuple(args, ":get_subject"))
32 return NULL;
33
34 if ((name = X509_REQ_get_subject_name(self->x509_req)) == NULL)
35 {
36 exception_from_error_queue();
37 return NULL;
38 }
Jean-Paul Calderone2aa2b332008-03-06 21:43:14 -050039 if ((pyname = crypto_X509Name_New(name, 0)) != NULL) {
40 pyname->parent_cert = (PyObject *)self;
41 Py_INCREF(self);
42 }
43 return (PyObject *)pyname;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050044}
45
46static char crypto_X509Req_get_pubkey_doc[] = "\n\
47Get the public key from the certificate request\n\
48\n\
49Arguments: self - The X509Req object\n\
50 args - The Python argument tuple, should be empty\n\
51Returns: The public key\n\
52";
53
54static PyObject *
55crypto_X509Req_get_pubkey(crypto_X509ReqObj *self, PyObject *args)
56{
57 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
58 EVP_PKEY *pkey;
59
60 if (!PyArg_ParseTuple(args, ":get_pubkey"))
61 return NULL;
62
63 if ((pkey = X509_REQ_get_pubkey(self->x509_req)) == NULL)
64 {
65 exception_from_error_queue();
66 return NULL;
67 }
68
69 return (PyObject *)crypto_PKey_New(pkey, 1);
70}
71
72static char crypto_X509Req_set_pubkey_doc[] = "\n\
73Set the public key of the certificate request\n\
74\n\
75Arguments: self - The X509Req object\n\
76 args - The Python argument tuple, should be:\n\
77 pkey - The public key to use\n\
78Returns: None\n\
79";
80
81static PyObject *
82crypto_X509Req_set_pubkey(crypto_X509ReqObj *self, PyObject *args)
83{
84 crypto_PKeyObj *pkey;
85
86 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
87 return NULL;
88
89 if (!X509_REQ_set_pubkey(self->x509_req, pkey->pkey))
90 {
91 exception_from_error_queue();
92 return NULL;
93 }
94
95 Py_INCREF(Py_None);
96 return Py_None;
97}
98
99static char crypto_X509Req_sign_doc[] = "\n\
100Sign the certificate request using the supplied key and digest\n\
101\n\
102Arguments: self - The X509Req object\n\
103 args - The Python argument tuple, should be:\n\
104 pkey - The key to sign with\n\
105 digest - The message digest to use\n\
106Returns: None\n\
107";
108
109static PyObject *
110crypto_X509Req_sign(crypto_X509ReqObj *self, PyObject *args)
111{
112 crypto_PKeyObj *pkey;
113 char *digest_name;
114 const EVP_MD *digest;
115
116 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
117 &digest_name))
118 return NULL;
119
120 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
121 {
122 PyErr_SetString(PyExc_ValueError, "No such digest method");
123 return NULL;
124 }
125
126 if (!X509_REQ_sign(self->x509_req, pkey->pkey, digest))
127 {
128 exception_from_error_queue();
129 return NULL;
130 }
131
132 Py_INCREF(Py_None);
133 return Py_None;
134}
135
136static char crypto_X509Req_verify_doc[] = "\n\
137Verifies a certificate request using the supplied public key\n\
138 \n\
139Arguments: self - X509Req object\n\
140 args - The Python argument tuple, should be:\n\
141 key - a public key\n\
142Returns: True, if the signature is correct, 0 otherwise.\n\
143";
144
145PyObject *
146crypto_X509Req_verify(crypto_X509ReqObj *self, PyObject *args)
147{
148 PyObject *obj;
149 crypto_PKeyObj *key;
150 int answer;
151
152 if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &obj))
153 return NULL;
154
155 key = (crypto_PKeyObj *)obj;
156
157 if ((answer = X509_REQ_verify(self->x509_req, key->pkey)) < 0)
158 {
159 exception_from_error_queue();
160 return NULL;
161 }
162
163 return PyInt_FromLong(answer);
164}
165
166static char crypto_X509Req_add_extensions_doc[] = "\n\
167Add extensions to the request.\n\
168\n\
169Arguments: self - X509Req object\n\
170 args - The Python argument tuple, should be:\n\
171 extensions - a sequence of X509Extension objects\n\
172Returns: None\n\
173";
174
175static PyObject *
176crypto_X509Req_add_extensions(crypto_X509ReqObj *self, PyObject *args)
177{
178 PyObject *extensions;
179 crypto_X509ExtensionObj *ext;
180 STACK_OF(X509_EXTENSION) *exts;
181 int nr_of_extensions, i;
182
183 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
184 return NULL;
185
186 if (!PySequence_Check(extensions))
187 {
188 PyErr_SetString(PyExc_TypeError, "Expected a sequence");
189 return NULL;
190 }
191
192 /* Make a STACK_OF(X509_EXTENSION) from sequence */
193 if ((exts = sk_X509_EXTENSION_new_null()) == NULL)
194 {
195 exception_from_error_queue();
196 return NULL;
197 }
198
199 /* Put the extensions in a stack */
200 nr_of_extensions = PySequence_Length(extensions);
201
202 for (i = 0; i < nr_of_extensions; i++)
203 {
204 ext = (crypto_X509ExtensionObj *)PySequence_GetItem(extensions, i);
205 if (!(crypto_X509Extension_Check(ext)))
206 {
207 PyErr_SetString(PyExc_ValueError,
208 "One of the elements is not an X509Extension");
209 sk_X509_EXTENSION_free(exts);
210 return NULL;
211 }
212 sk_X509_EXTENSION_push(exts, ext->x509_extension);
213 }
214
215 if (!X509_REQ_add_extensions(self->x509_req, exts))
216 {
217 sk_X509_EXTENSION_free(exts);
218 exception_from_error_queue();
219 return NULL;
220 }
221
222 sk_X509_EXTENSION_free(exts);
223
224 Py_INCREF(Py_None);
225 return Py_None;
226}
227
228/*
229 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
230 * { 'name', (PyCFunction)crypto_X509Req_name, METH_VARARGS }
231 * for convenience
232 */
233#define ADD_METHOD(name) \
234 { #name, (PyCFunction)crypto_X509Req_##name, METH_VARARGS, crypto_X509Req_##name##_doc }
235static PyMethodDef crypto_X509Req_methods[] =
236{
237 ADD_METHOD(get_subject),
238 ADD_METHOD(get_pubkey),
239 ADD_METHOD(set_pubkey),
240 ADD_METHOD(sign),
241 ADD_METHOD(verify),
242 ADD_METHOD(add_extensions),
243 { NULL, NULL }
244};
245#undef ADD_METHOD
246
247
248/*
249 * Constructor for X509Req, never called by Python code directly
250 *
251 * Arguments: name - A "real" X509_REQ object
252 * dealloc - Boolean value to specify whether the destructor should
253 * free the "real" X509_REQ object
254 * Returns: The newly created X509Req object
255 */
256crypto_X509ReqObj *
257crypto_X509Req_New(X509_REQ *req, int dealloc)
258{
259 crypto_X509ReqObj *self;
260
261 self = PyObject_New(crypto_X509ReqObj, &crypto_X509Req_Type);
262
263 if (self == NULL)
264 return NULL;
265
266 self->x509_req = req;
267 self->dealloc = dealloc;
268
269 return self;
270}
271
272/*
273 * Deallocate the memory used by the X509Req object
274 *
275 * Arguments: self - The X509Req object
276 * Returns: None
277 */
278static void
279crypto_X509Req_dealloc(crypto_X509ReqObj *self)
280{
281 /* Sometimes we don't have to dealloc this */
282 if (self->dealloc)
283 X509_REQ_free(self->x509_req);
284
285 PyObject_Del(self);
286}
287
288
289/*
290 * Find attribute.
291 *
292 * Arguments: self - The X509Req object
293 * name - The attribute name
294 * Returns: A Python object for the attribute, or NULL if something went
295 * wrong
296 */
297static PyObject *
298crypto_X509Req_getattr(crypto_X509ReqObj *self, char *name)
299{
300 return Py_FindMethod(crypto_X509Req_methods, (PyObject *)self, name);
301}
302
303PyTypeObject crypto_X509Req_Type = {
304 PyObject_HEAD_INIT(NULL)
305 0,
306 "X509Req",
307 sizeof(crypto_X509ReqObj),
308 0,
309 (destructor)crypto_X509Req_dealloc,
310 NULL, /* print */
311 (getattrfunc)crypto_X509Req_getattr,
312};
313
314
315/*
316 * Initialize the X509Req part of the crypto module
317 *
318 * Arguments: dict - The crypto module dictionary
319 * Returns: None
320 */
321int
322init_crypto_x509req(PyObject *dict)
323{
324 crypto_X509Req_Type.ob_type = &PyType_Type;
325 Py_INCREF(&crypto_X509Req_Type);
326 PyDict_SetItemString(dict, "X509ReqType", (PyObject *)&crypto_X509Req_Type);
327 return 1;
328}