/******************************************************************************/
/* */
/* X r d C r y p t o s s l X 5 0 9 R e q. c c */
/* */
/* (c) 2005 G. Ganis , CERN */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/* */
/******************************************************************************/
/* ************************************************************************** */
/* */
/* OpenSSL implementation of XrdCryptoX509Req */
/* */
/* ************************************************************************** */
#include
#include
#include
#include
#include "XrdCrypto/XrdCryptosslRSA.hh"
#include "XrdCrypto/XrdCryptosslX509Req.hh"
#include "XrdCrypto/XrdCryptosslAux.hh"
#include "XrdCrypto/XrdCryptosslTrace.hh"
#include
//_____________________________________________________________________________
XrdCryptosslX509Req::XrdCryptosslX509Req(XrdSutBucket *buck) : XrdCryptoX509Req()
{
// Constructor certificate from BIO 'bcer'
EPNAME("X509Req::XrdCryptosslX509Req_bio");
// Init private members
creq = 0; // The certificate object
subject = ""; // subject;
subjecthash = ""; // hash of subject;
subjectoldhash = ""; // hash of subject (md5 algorithm);
bucket = 0; // bucket for serialization
pki = 0; // PKI of the certificate
// Make sure we got something;
if (!buck) {
DEBUG("got undefined opaque buffer");
return;
}
//
// Create a bio_mem to store the certificates
BIO *bmem = BIO_new(BIO_s_mem());
if (!bmem) {
DEBUG("unable to create BIO for memory operations");
return;
}
// Write data to BIO
int nw = BIO_write(bmem,(const void *)(buck->buffer),buck->size);
if (nw != buck->size) {
DEBUG("problems writing data to memory BIO (nw: "< 0) ? subject.c_str() : (const char *)0;
}
//_____________________________________________________________________________
const char *XrdCryptosslX509Req::SubjectHash(int alg)
{
// Return hash of subject name
// Use default algorithm (X509_NAME_hash) for alg = 0, old algorithm
// (for v>=1.0.0) when alg = 1
EPNAME("X509::SubjectHash");
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(__APPLE__))
if (alg == 1) {
// md5 based
if (subjectoldhash.length() <= 0) {
// Make sure we have a certificate
if (creq) {
char chash[30] = {0};
snprintf(chash, sizeof(chash),
"%08lx.0",X509_NAME_hash_old(X509_REQ_get_subject_name(creq)));
subjectoldhash = chash;
} else {
DEBUG("WARNING: no certificate available - cannot extract subject hash (md5)");
}
}
// return what we have
return (subjectoldhash.length() > 0) ? subjectoldhash.c_str() : (const char *)0;
}
#else
if (alg == 1) { }
#endif
// If we do not have it already, try extraction
if (subjecthash.length() <= 0) {
// Make sure we have a certificate
if (creq) {
char chash[30] = {0};
snprintf(chash, sizeof(chash),
"%08lx.0",X509_NAME_hash(X509_REQ_get_subject_name(creq)));
subjecthash = chash;
} else {
DEBUG("WARNING: no certificate available - cannot extract subject hash (default)");
}
}
// return what we have
return (subjecthash.length() > 0) ? subjecthash.c_str() : (const char *)0;
}
//_____________________________________________________________________________
XrdCryptoX509Reqdata XrdCryptosslX509Req::GetExtension(const char *oid)
{
// Return issuer name
EPNAME("X509Req::GetExtension");
XrdCryptoX509Reqdata ext = 0;
// Make sure we got something to look for
if (!oid) {
DEBUG("OID string not defined");
return ext;
}
// Make sure we got something to look for
if (!creq) {
DEBUG("certificate is not initialized");
return ext;
}
// Are there any extension?
STACK_OF(X509_EXTENSION) *esk = X509_REQ_get_extensions(creq);
//
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
int numext = sk_X509_EXTENSION_num(esk);
#else /* OPENSSL */
int numext = sk_num(esk);
#endif /* OPENSSL */
if (numext <= 0) {
DEBUG("certificate has got no extensions");
return ext;
}
DEBUG("certificate request has "< 0);
// Loop to identify the one we would like
int i = 0;
X509_EXTENSION *wext = 0;
for (i = 0; i< numext; i++) {
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
wext = sk_X509_EXTENSION_value(esk, i);
#else /* OPENSSL */
wext = (X509_EXTENSION *)sk_value(esk, i);
#endif /* OPENSSL */
if (usenid) {
int enid = OBJ_obj2nid(X509_EXTENSION_get_object(wext));
if (enid == nid)
break;
} else {
// Try matching of the text
char s[256];
OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(wext), 1);
if (!strcmp(s, oid))
break;
}
wext = 0;
}
// We are done if nothing was found
if (!wext) {
DEBUG("Extension "<size<<" bytes)");
return bucket;
}
// Make sure we got something to export
if (!creq) {
DEBUG("certificate is not initialized");
return 0;
}
//
// Now we create a bio_mem to serialize the certificate
BIO *bmem = BIO_new(BIO_s_mem());
if (!bmem) {
DEBUG("unable to create BIO for memory operations");
return 0;
}
// Write certificate to BIO
if (!PEM_write_bio_X509_REQ(bmem, creq)) {
DEBUG("unable to write certificate request to memory BIO");
return 0;
}
// Extract pointer to BIO data and length of segment
char *bdata = 0;
int blen = BIO_get_mem_data(bmem, &bdata);
DEBUG("BIO data: "<SetBuf(bdata, blen);
DEBUG("result of serialization: "<size<<" bytes");
} else {
DEBUG("unable to create bucket for serialized format");
BIO_free(bmem);
return 0;
}
//
// Free BIO
BIO_free(bmem);
//
// We are done
return bucket;
}
//_____________________________________________________________________________
bool XrdCryptosslX509Req::Verify()
{
// Verify signature of the request
EPNAME("X509Req::Verify");
// We must have been initialized
if (!creq)
return 0;
// Ok: we can verify
int rc = X509_REQ_verify(creq,X509_REQ_get_pubkey(creq));
if (rc <= 0) {
// Failure
if (rc == 0) {
// Signatures are not OK
DEBUG("signature not OK");
} else {
// General failure
DEBUG("could not verify signature");
}
return 0;
}
// OK
return 1;
}