Loading...
Searching...
No Matches
XrdCryptosslX509Req.cc
Go to the documentation of this file.
/******************************************************************************/
/* */
/* 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 <http://www.gnu.org/licenses/>. */
/* */
/* 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 <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno>
#include "XrdCrypto/XrdCryptosslRSA.hh"
#include "XrdCrypto/XrdCryptosslX509Req.hh"
#include "XrdCrypto/XrdCryptosslAux.hh"
#include "XrdCrypto/XrdCryptosslTrace.hh"
#include <openssl/pem.h>
//_____________________________________________________________________________
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: "<<nw<<")");
return;
}
// Get certificate request from BIO
if (!PEM_read_bio_X509_REQ(bmem,&creq,0,0)) {
DEBUG("unable to read certificate request to memory BIO");
return;
}
//
// Free BIO
BIO_free(bmem);
//
// Init some of the private members (the others upon need)
Subject();
//
// Get the public key
EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
//
if (evpp) {
// init pki with the partial key
if (!pki)
pki = new XrdCryptosslRSA(evpp, 0);
} else {
DEBUG("could not access the public key");
}
}
//_____________________________________________________________________________
XrdCryptosslX509Req::XrdCryptosslX509Req(X509_REQ *xc) : XrdCryptoX509Req()
{
// Constructor: import X509_REQ object
EPNAME("X509Req::XrdCryptosslX509Req_x509");
// 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 (!xc) {
DEBUG("got undefined X509 object");
return;
}
// Set certificate
creq = xc;
//
// Init some of the private members (the others upon need)
Subject();
//
// Get the public key
EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
//
if (evpp) {
// init pki with the partial key
if (!pki)
pki = new XrdCryptosslRSA(evpp, 0);
} else {
DEBUG("could not access the public key");
}
}
//_____________________________________________________________________________
XrdCryptosslX509Req::~XrdCryptosslX509Req()
{
// Destructor
// Cleanup certificate
if (creq) X509_REQ_free(creq);
// Cleanup key
if (pki) delete pki;
}
//_____________________________________________________________________________
const char *XrdCryptosslX509Req::Subject()
{
// Return subject name
EPNAME("X509Req::Subject");
// If we do not have it already, try extraction
if (subject.length() <= 0) {
// Make sure we have a certificate
if (!creq) {
DEBUG("WARNING: no certificate available - cannot extract subject name");
return (const char *)0;
}
// Extract subject name
XrdCryptosslNameOneLine(X509_REQ_get_subject_name(creq), subject);
}
// return what we have
return (subject.length() > 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 "<<numext<<" extensions");
// If the string is the Standard Name of a known extension check
// searche the corresponding NID
int nid = OBJ_sn2nid(oid);
bool usenid = (nid > 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 "<<oid<<" not found");
return ext;
}
// We are done
return (XrdCryptoX509Reqdata)wext;
}
//_____________________________________________________________________________
XrdSutBucket *XrdCryptosslX509Req::Export()
{
// Export in form of bucket
EPNAME("X509Req::Export");
// If we have already done it, return the previous result
if (bucket) {
DEBUG("serialization already performed:"
" return previous result ("<<bucket->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: "<<blen<<" bytes at 0x"<<(int *)bdata);
// create the bucket now
bucket = new XrdSutBucket(0,0,kXRS_x509_req);
if (bucket) {
// Fill bucket
bucket->SetBuf(bdata, blen);
DEBUG("result of serialization: "<<bucket->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;
}
DEBUG
#define DEBUG(x)
Definition XrdBwmTrace.hh:54
EPNAME
#define EPNAME(x)
Definition XrdBwmTrace.hh:56
XrdCryptoX509Reqdata
void * XrdCryptoX509Reqdata
Definition XrdCryptoX509Req.hh:42
XrdCryptosslNameOneLine
void XrdCryptosslNameOneLine(X509_NAME *nm, XrdOucString &s)
Definition XrdCryptosslAux.cc:744
XrdCryptosslAux.hh
XrdCryptosslRSA.hh
XrdCryptosslTrace.hh
XrdCryptosslX509Req.hh
kXRS_x509_req
@ kXRS_x509_req
Definition XrdSutAux.hh:81
XrdCryptoX509Req::SubjectHash
const char * SubjectHash()
Definition XrdCryptoX509Req.hh:74
XrdCryptoX509Req::XrdCryptoX509Req
XrdCryptoX509Req(int v=-1)
Definition XrdCryptoX509Req.hh:53
XrdCryptosslRSA
Definition XrdCryptosslRSA.hh:47
XrdCryptosslX509Req::XrdCryptosslX509Req
XrdCryptosslX509Req(XrdSutBucket *bck)
Definition XrdCryptosslX509Req.cc:47
XrdCryptosslX509Req::GetExtension
XrdCryptoX509Reqdata GetExtension(const char *oid)
Definition XrdCryptosslX509Req.cc:225
XrdCryptosslX509Req::Verify
bool Verify()
Definition XrdCryptosslX509Req.cc:353
XrdCryptosslX509Req::Export
XrdSutBucket * Export()
Definition XrdCryptosslX509Req.cc:296
XrdCryptosslX509Req::Subject
const char * Subject()
Definition XrdCryptosslX509Req.cc:155
XrdCryptosslX509Req::~XrdCryptosslX509Req
virtual ~XrdCryptosslX509Req()
Definition XrdCryptosslX509Req.cc:144
XrdSutBucket
Definition XrdSutBucket.hh:44
XrdSutBucket::size
kXR_int32 size
Definition XrdSutBucket.hh:47
XrdSutBucket::buffer
char * buffer
Definition XrdSutBucket.hh:48