XRootD
Loading...
Searching...
No Matches
XrdCryptosslX509Req.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d C r y p t o s s l X 5 0 9 R e q. c c */
4/* */
5/* (c) 2005 G. Ganis , CERN */
6/* */
7/* This file is part of the XRootD software suite. */
8/* */
9/* XRootD is free software: you can redistribute it and/or modify it under */
10/* the terms of the GNU Lesser General Public License as published by the */
11/* Free Software Foundation, either version 3 of the License, or (at your */
12/* option) any later version. */
13/* */
14/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
15/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
16/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
17/* License for more details. */
18/* */
19/* You should have received a copy of the GNU Lesser General Public License */
20/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
21/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
22/* */
23/* The copyright holder's institutional names and contributor's names may not */
24/* be used to endorse or promote products derived from this software without */
25/* specific prior written permission of the institution or contributor. */
26/* */
27/******************************************************************************/
28
29/* ************************************************************************** */
30/* */
31/* OpenSSL implementation of XrdCryptoX509Req */
32/* */
33/* ************************************************************************** */
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <cerrno>
38
43
44#include <openssl/pem.h>
45
46//_____________________________________________________________________________
48{
49 // Constructor certificate from BIO 'bcer'
50 EPNAME("X509Req::XrdCryptosslX509Req_bio");
51
52 // Init private members
53 creq = 0; // The certificate object
54 subject = ""; // subject;
55 subjecthash = ""; // hash of subject;
56 subjectoldhash = ""; // hash of subject (md5 algorithm);
57 bucket = 0; // bucket for serialization
58 pki = 0; // PKI of the certificate
59
60 // Make sure we got something;
61 if (!buck) {
62 DEBUG("got undefined opaque buffer");
63 return;
64 }
65
66 //
67 // Create a bio_mem to store the certificates
68 BIO *bmem = BIO_new(BIO_s_mem());
69 if (!bmem) {
70 DEBUG("unable to create BIO for memory operations");
71 return;
72 }
73
74 // Write data to BIO
75 int nw = BIO_write(bmem,(const void *)(buck->buffer),buck->size);
76 if (nw != buck->size) {
77 DEBUG("problems writing data to memory BIO (nw: "<<nw<<")");
78 return;
79 }
80
81 // Get certificate request from BIO
82 if (!PEM_read_bio_X509_REQ(bmem,&creq,0,0)) {
83 DEBUG("unable to read certificate request to memory BIO");
84 return;
85 }
86 //
87 // Free BIO
88 BIO_free(bmem);
89 //
90 // Init some of the private members (the others upon need)
91 Subject();
92 //
93 // Get the public key
94 EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
95 //
96 if (evpp) {
97 // init pki with the partial key
98 if (!pki)
99 pki = new XrdCryptosslRSA(evpp, 0);
100 } else {
101 DEBUG("could not access the public key");
102 }
103}
104
105//_____________________________________________________________________________
107{
108 // Constructor: import X509_REQ object
109 EPNAME("X509Req::XrdCryptosslX509Req_x509");
110
111 // Init private members
112 creq = 0; // The certificate object
113 subject = ""; // subject;
114 subjecthash = ""; // hash of subject;
115 subjectoldhash = ""; // hash of subject (md5 algorithm);
116 bucket = 0; // bucket for serialization
117 pki = 0; // PKI of the certificate
118
119 // Make sure we got something;
120 if (!xc) {
121 DEBUG("got undefined X509 object");
122 return;
123 }
124
125 // Set certificate
126 creq = xc;
127 //
128 // Init some of the private members (the others upon need)
129 Subject();
130 //
131 // Get the public key
132 EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
133 //
134 if (evpp) {
135 // init pki with the partial key
136 if (!pki)
137 pki = new XrdCryptosslRSA(evpp, 0);
138 } else {
139 DEBUG("could not access the public key");
140 }
141}
142
143//_____________________________________________________________________________
145{
146 // Destructor
147
148 // Cleanup certificate
149 if (creq) X509_REQ_free(creq);
150 // Cleanup key
151 if (pki) delete pki;
152}
153
154//_____________________________________________________________________________
156{
157 // Return subject name
158 EPNAME("X509Req::Subject");
159
160 // If we do not have it already, try extraction
161 if (subject.length() <= 0) {
162
163 // Make sure we have a certificate
164 if (!creq) {
165 DEBUG("WARNING: no certificate available - cannot extract subject name");
166 return (const char *)0;
167 }
168
169 // Extract subject name
170 XrdCryptosslNameOneLine(X509_REQ_get_subject_name(creq), subject);
171 }
172
173 // return what we have
174 return (subject.length() > 0) ? subject.c_str() : (const char *)0;
175}
176
177//_____________________________________________________________________________
179{
180 // Return hash of subject name
181 // Use default algorithm (X509_NAME_hash) for alg = 0, old algorithm
182 // (for v>=1.0.0) when alg = 1
183 EPNAME("X509::SubjectHash");
184
185 if (alg == 1) {
186 // md5 based
187 if (subjectoldhash.length() <= 0) {
188 // Make sure we have a certificate
189 if (creq) {
190 char chash[30] = {0};
191 snprintf(chash, sizeof(chash),
192 "%08lx.0",X509_NAME_hash_old(X509_REQ_get_subject_name(creq)));
193 subjectoldhash = chash;
194 } else {
195 DEBUG("WARNING: no certificate available - cannot extract subject hash (md5)");
196 }
197 }
198 // return what we have
199 return (subjectoldhash.length() > 0) ? subjectoldhash.c_str() : (const char *)0;
200 }
201
202 // If we do not have it already, try extraction
203 if (subjecthash.length() <= 0) {
204
205 // Make sure we have a certificate
206 if (creq) {
207 char chash[30] = {0};
208 snprintf(chash, sizeof(chash),
209 "%08lx.0",X509_NAME_hash(X509_REQ_get_subject_name(creq)));
210 subjecthash = chash;
211 } else {
212 DEBUG("WARNING: no certificate available - cannot extract subject hash (default)");
213 }
214 }
215
216 // return what we have
217 return (subjecthash.length() > 0) ? subjecthash.c_str() : (const char *)0;
218}
219
220//_____________________________________________________________________________
222{
223 // Return issuer name
224 EPNAME("X509Req::GetExtension");
225 XrdCryptoX509Reqdata ext = 0;
226
227 // Make sure we got something to look for
228 if (!oid) {
229 DEBUG("OID string not defined");
230 return ext;
231 }
232
233 // Make sure we got something to look for
234 if (!creq) {
235 DEBUG("certificate is not initialized");
236 return ext;
237 }
238
239 // Are there any extension?
240 STACK_OF(X509_EXTENSION) *esk = X509_REQ_get_extensions(creq);
241 //
242 int numext = sk_X509_EXTENSION_num(esk);
243 if (numext <= 0) {
244 DEBUG("certificate has got no extensions");
245 return ext;
246 }
247 DEBUG("certificate request has "<<numext<<" extensions");
248
249 // If the string is the Standard Name of a known extension check
250 // searche the corresponding NID
251 int nid = OBJ_sn2nid(oid);
252 bool usenid = (nid > 0);
253
254 // Loop to identify the one we would like
255 int i = 0;
256 X509_EXTENSION *wext = 0;
257 for (i = 0; i< numext; i++) {
258 wext = sk_X509_EXTENSION_value(esk, i);
259 if (usenid) {
260 int enid = OBJ_obj2nid(X509_EXTENSION_get_object(wext));
261 if (enid == nid)
262 break;
263 } else {
264 // Try matching of the text
265 char s[256];
266 OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(wext), 1);
267 if (!strcmp(s, oid))
268 break;
269 }
270 wext = 0;
271 }
272
273 // We are done if nothing was found
274 if (!wext) {
275 DEBUG("Extension "<<oid<<" not found");
276 return ext;
277 }
278
279 // We are done
280 return (XrdCryptoX509Reqdata)wext;
281}
282
283//_____________________________________________________________________________
285{
286 // Export in form of bucket
287 EPNAME("X509Req::Export");
288
289 // If we have already done it, return the previous result
290 if (bucket) {
291 DEBUG("serialization already performed:"
292 " return previous result ("<<bucket->size<<" bytes)");
293 return bucket;
294 }
295
296 // Make sure we got something to export
297 if (!creq) {
298 DEBUG("certificate is not initialized");
299 return 0;
300 }
301
302 //
303 // Now we create a bio_mem to serialize the certificate
304 BIO *bmem = BIO_new(BIO_s_mem());
305 if (!bmem) {
306 DEBUG("unable to create BIO for memory operations");
307 return 0;
308 }
309
310 // Write certificate to BIO
311 if (!PEM_write_bio_X509_REQ(bmem, creq)) {
312 DEBUG("unable to write certificate request to memory BIO");
313 return 0;
314 }
315
316 // Extract pointer to BIO data and length of segment
317 char *bdata = 0;
318 int blen = BIO_get_mem_data(bmem, &bdata);
319 DEBUG("BIO data: "<<blen<<" bytes at 0x"<<(int *)bdata);
320
321 // create the bucket now
322 bucket = new XrdSutBucket(0,0,kXRS_x509_req);
323 if (bucket) {
324 // Fill bucket
325 bucket->SetBuf(bdata, blen);
326 DEBUG("result of serialization: "<<bucket->size<<" bytes");
327 } else {
328 DEBUG("unable to create bucket for serialized format");
329 BIO_free(bmem);
330 return 0;
331 }
332 //
333 // Free BIO
334 BIO_free(bmem);
335 //
336 // We are done
337 return bucket;
338}
339
340//_____________________________________________________________________________
342{
343 // Verify signature of the request
344 EPNAME("X509Req::Verify");
345
346 // We must have been initialized
347 if (!creq)
348 return 0;
349
350 // Ok: we can verify
351 int rc = X509_REQ_verify(creq,X509_REQ_get_pubkey(creq));
352 if (rc <= 0) {
353 // Failure
354 if (rc == 0) {
355 // Signatures are not OK
356 DEBUG("signature not OK");
357 } else {
358 // General failure
359 DEBUG("could not verify signature");
360 }
361 return 0;
362 }
363 // OK
364 return 1;
365}
#define DEBUG(x)
#define EPNAME(x)
void * XrdCryptoX509Reqdata
void XrdCryptosslNameOneLine(X509_NAME *nm, XrdOucString &s)
@ kXRS_x509_req
Definition XrdSutAux.hh:81
const char * SubjectHash()
XrdCryptosslX509Req(XrdSutBucket *bck)
XrdCryptoX509Reqdata GetExtension(const char *oid)
kXR_int32 size