-#ifdef HAVE_TLS
-#include <openssl/x509.h>
-#include <openssl/err.h>
-
-/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
- * x509_name must be an (X509_NAME *). If func is non-NULL, the
- * constructed DN will use numeric OIDs to identify attributeTypes,
- * and the func() will be invoked to rewrite the DN with the given
- * flags.
- *
- * Otherwise the DN will use shortNames as defined in the OpenSSL
- * library.
- *
- * It's preferable to let slapd do the OID to attributeType mapping,
- * because the OpenSSL tables are known to have many typos in versions
- * up to (at least) 0.9.6c. However, the LDAP client has no schema tables,
- * so we're forced to use OpenSSL's mapping there.
- * -- Howard Chu 2002-04-18
- */
-
-int
-ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
- unsigned flags )
-{
- LDAPDN *newDN;
- LDAPRDN *newRDN;
- LDAPAVA *newAVA, *baseAVA;
- X509_NAME_ENTRY *ne;
- ASN1_OBJECT *obj;
- ASN1_STRING *str;
- char oids[8192], *oidptr = oids, *oidbuf;
- void *ptrs[2048];
- int i, j, k, navas, nrdns, rc = LDAP_SUCCESS;
- int set = 0;
- size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
- int csize;
-
- struct berval Val;
-
- assert( bv );
- bv->bv_len = 0;
- bv->bv_val = NULL;
-
- /* Get the number of AVAs. This is not necessarily the same as
- * the number of RDNs.
- */
- navas = X509_NAME_entry_count( x509_name );
-
- /* Get the last element, to see how many RDNs there are */
- ne = X509_NAME_get_entry( x509_name, navas - 1 );
- nrdns = ne->set + 1;
-
- /* Allocate the DN/RDN/AVA stuff as a single block */
- dnsize = sizeof(LDAPDN) + sizeof(LDAPRDN *) * (nrdns+1);
- dnsize += sizeof(LDAPRDN) * nrdns + sizeof(LDAPAVA *) * (navas+nrdns);
- dnsize += sizeof(LDAPAVA) * navas;
- if (dnsize > sizeof(ptrs)) {
- newDN = (LDAPDN *)LDAP_MALLOC( dnsize );
- if ( newDN == NULL )
- return LDAP_NO_MEMORY;
- } else {
- newDN = (LDAPDN *)ptrs;
- }
-
- newDN[0] = (LDAPRDN**)(newDN+1);
- newDN[0][nrdns] = NULL;
- newRDN = (LDAPRDN*)(newDN[0] + nrdns+1);
- newAVA = (LDAPAVA*)(newRDN + navas + nrdns*2);
- baseAVA = newAVA;
-
- /* Retrieve RDNs in reverse order; LDAP is backwards from X.500. */
- for ( i = nrdns - 1, j = 0; i >= 0; i-- ) {
- ne = X509_NAME_get_entry( x509_name, i );
- obj = X509_NAME_ENTRY_get_object( ne );
- str = X509_NAME_ENTRY_get_data( ne );
-
- /* If set changed, move to next RDN */
- if ( set != ne->set ) {
- /* If this is not the first time, end the
- * previous RDN and advance.
- */
- if ( j > 0 ) {
- newRDN[0][k] = NULL;
- newRDN = (LDAPRDN*)(newRDN[0]+k+1);
- }
- newDN[0][j++] = newRDN;
-
- newRDN[0] = (LDAPAVA**)(newRDN+1);
- k = 0;
- set = ne->set;
- }
-
- if ( !func ) {
- int n = OBJ_obj2nid( obj );
-
- if (n == NID_undef)
- goto get_oid;
- newAVA->la_attr.bv_val = (char *)OBJ_nid2sn( n );
- newAVA->la_attr.bv_len = strlen( newAVA->la_attr.bv_val );
- } else {
-get_oid: newAVA->la_attr.bv_val = oidptr;
- newAVA->la_attr.bv_len = OBJ_obj2txt( oidptr, oidrem, obj, 1 );
- oidptr += newAVA->la_attr.bv_len + 1;
- oidrem -= newAVA->la_attr.bv_len + 1;
-
- /* Running out of OID buffer space? */
- if (oidrem < 128) {
- if ( oidsize == 0 ) {
- oidsize = sizeof(oids) * 2;
- oidrem = oidsize;
- oidbuf = LDAP_MALLOC( oidsize );
- if ( oidbuf == NULL ) goto nomem;
- oidptr = oidbuf;
- } else {
- char *old = oidbuf;
- oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
- if ( oidbuf == NULL ) goto nomem;
- /* Buffer moved! Fix AVA pointers */
- if ( old != oidbuf ) {
- LDAPAVA *a;
- long dif = oidbuf - old;
-
- for (a=baseAVA; a<=newAVA; a++){
- if (a->la_attr.bv_val >= old &&
- a->la_attr.bv_val <= (old + oidsize))
- a->la_attr.bv_val += dif;
- }
- }
- oidptr = oidbuf + oidsize - oidrem;
- oidrem += oidsize;
- oidsize *= 2;
- }
- }
- }
- Val.bv_val = str->data;
- Val.bv_len = str->length;
- switch( str->type ) {
- case V_ASN1_UNIVERSALSTRING:
- /* This uses 32-bit ISO 10646-1 */
- csize = 4; goto to_utf8;
- case V_ASN1_BMPSTRING:
- /* This uses 16-bit ISO 10646-1 */
- csize = 2; goto to_utf8;
- case V_ASN1_T61STRING:
- /* This uses 8-bit, assume ISO 8859-1 */
- csize = 1;
-to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
- if (rc != LDAP_SUCCESS) goto nomem;
- newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
- break;
- case V_ASN1_UTF8STRING:
- newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
- /* This is already in UTF-8 encoding */
- case V_ASN1_IA5STRING:
- case V_ASN1_PRINTABLESTRING:
- /* These are always 7-bit strings */
- ber_dupbv( &newAVA->la_value, &Val );
- default:
- ;
- }
- newRDN[0][k] = newAVA;
- newAVA++;
- k++;
- }
- newRDN[0][k] = NULL;
-
- if ( func ) {
- rc = func( newDN, flags );
- if ( rc != LDAP_SUCCESS )
- goto nomem;
- }
-
- rc = ldap_dn2bv( newDN, bv, LDAP_DN_FORMAT_LDAPV3 );
-
-nomem:
- for (;baseAVA < newAVA; baseAVA++) {
- LDAP_FREE( baseAVA->la_value.bv_val );
- }
-
- if ( oidsize != 0 )
- LDAP_FREE( oidbuf );
- if ( newDN != (LDAPDN*) ptrs )
- LDAP_FREE( newDN );
- return rc;
-}
-#endif /* HAVE_TLS */
-