>
> 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]

Reply via email to