>
> Anyway, I'd also like to have an easy way to extract LDAP-syntax
> DNs from certificates.
>
Here's some code which builds an LDAP string from an X509_NAME structure.
Its in C++ and probably needs some tightening up, but it may be useful.
One assumption is that the OpenSSL attribute type strings are the same as
the
LDAP ones.
//
// Function: BuildRealLDAPDN
//
// Description: Builds an LDAP style DN
//
static const int iAttributeTypeLength (64);
extern "C" char *BuildRealLDAPDN (const X509_NAME *pName, bool bTypeByOID =
false, bool bHexEncoding = false)
{
X509_NAME_ENTRY *pNameEntry = NULL; // RDN structure
int iI = 0; // RDN counter
int iDNLen = 0; // Length of text DN
int iN = 0; // Counter
int iJ = 0; // Counter
int iAttrTypeLen = 0; // Attribute type length
int iAttrValLen = 0; // Attribute value length
int iAttrXValLen = 0; // Expanded (escaped
characters) attribute value
int iCurrentPos = 0; // Current position in
buffer
int iSetCounter = 0; // Manages transition from
one RDN to the next
char *pCurrentPtr = NULL; // Pointer to current position
char *pType = NULL; // Current attribute type
tag
unsigned char *pAttrValData = NULL; // Pointer to attribute value
BUF_MEM *pBuffer = NULL; // Pointer to text DN buffer
char cAttributeType [iAttributeTypeLength]; // Attribute type buffer
static char hex [17]="0123456789ABCDEF"; // Hex array
static char nib2hex [0x10] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
if (pName == NULL)
return NULL;
if ((pBuffer = BUF_MEM_new ()) == NULL)
goto err;
if (!BUF_MEM_grow (pBuffer, 256)) // Allocate 256 bytes initially
goto err;
pBuffer -> data [0] ='\0'; // Initialise
for (iI = (sk_num (&(pName -> entries -> stack)) - 1); iI >= 0; iI--)
// Loop through the RDNs
pNameEntry = (X509_NAME_ENTRY *) sk_value (&(pName -> entries ->
stack),
iI); // Get RDN data structure
if (pNameEntry == NULL) //
Should never be NULL
goto err;
iN = OBJ_obj2nid (pNameEntry -> object); // Get
internal index for this OID
// Get a text tag for this attribute type
if (i2t_ASN1_OBJECT (&cAttributeType[0], iAttributeTypeLength,
pNameEntry -> object, bTypeByOID) == 0)
goto err;
iAttrTypeLen = strlen (&cAttributeType[0]);
iAttrValLen = pNameEntry -> value -> length;
pAttrValData = pNameEntry -> value -> data;
if (bHexEncoding == false) {
for (iAttrXValLen = iJ = 0; iJ < iAttrValLen; iJ++) {
iAttrXValLen++;
//
// Check the contents of the attribute value and if less
than 0x20 or greater than
// 0x7e, add an additional 2 bytes for the escape characters
//
if ((pAttrValData [iJ] < ' ') || (pAttrValData [iJ] > '~'))
iAttrXValLen += 3;
}
}
else
iAttrXValLen = iAttrValLen * 2 + 1; // Map each byte to 2
chars. Also leading # char
iCurrentPos = iDNLen;
if (iCurrentPos > 0)
iDNLen += iAttrTypeLen + 1 + iAttrXValLen + 1; // Add
space for the
=<,|+>
else
iDNLen = iAttrTypeLen + 1 + iAttrXValLen; // Add
space for the
=
if (!BUF_MEM_grow (pBuffer, iDNLen + 1))
goto err;
pCurrentPtr = &(pBuffer -> data [iCurrentPos]);
if (iCurrentPos > 0) {
if (pNameEntry -> set == iSetCounter) // Same set ? -
multi-valued RDN
*(pCurrentPtr++)='+';
else
*(pCurrentPtr++)=','; // Next RDN
}
iSetCounter = pNameEntry -> set; // Remember this set
index
// Add the attribute type tag to the buffer
memcpy (pCurrentPtr, &cAttributeType[0], iAttrTypeLen);
pCurrentPtr += iAttrTypeLen;
*(pCurrentPtr++) = '=';
pAttrValData = pNameEntry -> value -> data;
if (bHexEncoding == false) {
for (iJ = 0; iJ < iAttrValLen; iJ++) {
char c1;
char c2;
char n = pAttrValData [iJ];
//
// Escape the non-ASCII characters
//
if ((n < ' ') || (n > '~')) {
c1 = hex [(n >> 4) & 0x0f];
c2 = hex [n & 0x0f];
if (c1 != '0' || c2 != '0') {
*(pCurrentPtr++) = '\\';
*(pCurrentPtr++) = 'x';
*(pCurrentPtr++) = c1;
*(pCurrentPtr++) = c2;
}
else
iDNLen -= 4;
}
else
*(pCurrentPtr++) = n;
}
}
else {
unsigned char c;
*(pCurrentPtr++) = '#';
for (iJ = 0; iJ < iAttrValLen; iJ++) {
c = pAttrValData [iJ];
*(pCurrentPtr++) = nib2hex [(c & 0xf0) >> 4];
*(pCurrentPtr++) = nib2hex [(c & 0x0f)];
}
}
*pCurrentPtr = '\0';
}
pCurrentPtr= pBuffer -> data;
Free ((char *) pBuffer);
return pCurrentPtr;
err:
X509err(X509_F_X509_NAME_ONELINE,ERR_R_MALLOC_FAILURE);
if (pBuffer != NULL)
BUF_MEM_free (pBuffer);
return(NULL);
}
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]