/******************************************************************************/
/* */
/* X r d C r y p t o X 5 0 9 . 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. */
/* (c) 2012 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/******************************************************************************/
/* ************************************************************************** */
/* */
/* Abstract interface for X509 certificates. */
/* Allows to plug-in modules based on different crypto implementation */
/* (OpenSSL, Botan, ...) */
/* */
/* ************************************************************************** */
#include
#include "XrdCrypto/XrdCryptoX509.hh"
#include "XrdCrypto/XrdCryptoTrace.hh"
const char *XrdCryptoX509::ctype[4] = { "Unknown", "CA", "EEC", "Proxy" };
#define kAllowedSkew 600
//_____________________________________________________________________________
void XrdCryptoX509::Dump()
{
// Dump content
EPNAME("X509::Dump");
// Time strings
struct tm tst;
char stbeg[256] = {0};
time_t tbeg = NotBefore();
localtime_r(&tbeg,&tst);
asctime_r(&tst,stbeg);
stbeg[strlen(stbeg)-1] = 0;
char stend[256] = {0};
time_t tend = NotAfter();
localtime_r(&tend,&tst);
asctime_r(&tst,stend);
stend[strlen(stend)-1] = 0;
PRINT("+++++++++++++++ X509 dump +++++++++++++++++++++++");
PRINT("+");
PRINT("+ File: "<Status());
} else {
PRINT("+ PKI: missing");
}
PRINT("+");
PRINT("+++++++++++++++++++++++++++++++++++++++++++++++++");
}
//_____________________________________________________________________________
int XrdCryptoX509::BitStrength()
{
// Return number of bits in key
ABSTRACTMETHOD("XrdCryptoX509::BitStrength");
return -1;
}
//_____________________________________________________________________________
bool XrdCryptoX509::IsValid(int when)
{
// Check validity at local time 'when'. Use when =0 (default) to check
// at present time.
int now = (when > 0) ? when : (int)time(0);
// Correct for time zone (certificate times are UTC plus, eventually, DST
now -= XrdCryptoTZCorr();
return (now >= (NotBefore()-kAllowedSkew) && now <= NotAfter());
}
//_____________________________________________________________________________
bool XrdCryptoX509::IsExpired(int when)
{
// Check expiration at UTC time 'when'. Use when =0 (default) to check
// at present time.
int now = (when > 0) ? when : (int)time(0);
// Correct for time zone (certificate times are UTC plus, eventually, DST
now -= XrdCryptoTZCorr();
return (now > NotAfter());
}
//_____________________________________________________________________________
time_t XrdCryptoX509::NotBefore()
{
// Begin-validity time in secs since Epoch
ABSTRACTMETHOD("XrdCryptoX509::NotBefore");
return -1;
}
//_____________________________________________________________________________
time_t XrdCryptoX509::NotAfter()
{
// End-validity time in secs since Epoch
ABSTRACTMETHOD("XrdCryptoX509::NotAfter");
return -1;
}
//_____________________________________________________________________________
const char *XrdCryptoX509::Subject()
{
// Return subject name
ABSTRACTMETHOD("XrdCryptoX509::Subject");
return (const char *)0;
}
//_____________________________________________________________________________
const char *XrdCryptoX509::ParentFile()
{
// Return parent file name
ABSTRACTMETHOD("XrdCryptoX509::ParentFile");
return (const char *)0;
}
//_____________________________________________________________________________
const char *XrdCryptoX509::Issuer()
{
// Return issuer name
ABSTRACTMETHOD("XrdCryptoX509::Issuer");
return (const char *)0;
}
//_____________________________________________________________________________
const char *XrdCryptoX509::SubjectHash(int)
{
// Return subject name
ABSTRACTMETHOD("XrdCryptoX509::SubjectHash");
return (const char *)0;
}
//_____________________________________________________________________________
const char *XrdCryptoX509::IssuerHash(int)
{
// Return issuer name
ABSTRACTMETHOD("XrdCryptoX509::IssuerHash");
return (const char *)0;
}
//_____________________________________________________________________________
XrdCryptoX509data XrdCryptoX509::Opaque()
{
// Return underlying certificate in raw format
ABSTRACTMETHOD("XrdCryptoX509::Opaque");
return (XrdCryptoX509data)0;
}
//_____________________________________________________________________________
XrdCryptoRSA *XrdCryptoX509::PKI()
{
// Return PKI key of the certificate
ABSTRACTMETHOD("XrdCryptoX509::PKI");
return (XrdCryptoRSA *)0;
}
//_____________________________________________________________________________
void XrdCryptoX509::SetPKI(XrdCryptoX509data)
{
// Set PKI
ABSTRACTMETHOD("XrdCryptoX509::SetPKI");
}
//_____________________________________________________________________________
kXR_int64 XrdCryptoX509::SerialNumber()
{
// Return issuer name
ABSTRACTMETHOD("XrdCryptoX509::SerialNumber");
return -1;
}
//_____________________________________________________________________________
XrdOucString XrdCryptoX509::SerialNumberString()
{
// Return issuer name
ABSTRACTMETHOD("XrdCryptoX509::SerialNumberString");
return XrdOucString("");
}
//_____________________________________________________________________________
XrdCryptoX509data XrdCryptoX509::GetExtension(const char *)
{
// Return issuer name
ABSTRACTMETHOD("XrdCryptoX509::GetExtension");
return (XrdCryptoX509data)0;
}
//_____________________________________________________________________________
XrdSutBucket *XrdCryptoX509::Export()
{
// EXport in form of bucket
ABSTRACTMETHOD("XrdCryptoX509::Export");
return (XrdSutBucket *)0;
}
//_____________________________________________________________________________
bool XrdCryptoX509::Verify(XrdCryptoX509 *)
{
// Verify certificate signature with pub key of ref cert
ABSTRACTMETHOD("XrdCryptoX509::Verify");
return 0;
}
//_____________________________________________________________________________
int XrdCryptoX509::DumpExtensions(bool)
{
// Dump extensions, if any
ABSTRACTMETHOD("XrdCryptoX509::DumpExtensions");
return -1;
}
//_____________________________________________________________________________
bool XrdCryptoX509::MatchHostnames(const char * match_pattern, const char * hostname)
{
// Compare two hostnames and see if they are the same, including wildcards.
//
// For example,
//
// - foo.example.com and foo.example.com are considered equal.
// - bar.example.com and foo.example.com are not equal.
// - *.example.com and foo.example.com are equal.
// - *.example.com and foo.bar.example.com are NOT equal (wildcard applies to a single label).
// - FOO.example.com and foo.EXAMPLE.COM are equal (comparison is not case sensitive).
// - F*.com and foo.com are equal
//
// Returns true if the hostnames are considered a match
XrdOucString mpatt(match_pattern), hname(hostname);
// Not empty
if (!mpatt.length() || !hname.length()) return false;
// Create a lowercase copy of both hostnames
mpatt.lower(0);
hname.lower(0);
// Are they equal?
if (mpatt == hname) return true;
bool theydomatch = false;
// Get first token of both strings
int mfrom = -1, hfrom = -1;
XrdOucString mfirst, hfirst;
if (((mfrom = mpatt.tokenize(mfirst, mfrom, '.')) != -1) &&
((hfrom = hname.tokenize(hfirst, hfrom, '.')) != -1)) {
if (hfirst.matches(mfirst.c_str())) {
// First tokens matches, the rest should match without wildcards
mpatt.erasefromstart(mfrom);
hname.erasefromstart(hfrom);
if ((hname == mpatt) ||
(!hname.length() && !mpatt.length())) theydomatch = true;
}
}
return theydomatch;
}