/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2004 The OpenLDAP Foundation.
+ * Copyright 1998-2011 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* extension to UFN that turns trailing "dc=value" rdns in DNS style,
* e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */
#define DC_IN_UFN
-#if 0
-#define PRETTY_ESCAPE
-#endif
/* parsing/printing routines */
static int str2strval( const char *str, ber_len_t stoplen, struct berval *val,
char *dn;
BerElement tmp;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_get_dn\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
-#endif
assert( ld != NULL );
assert( LDAP_VALID(ld) );
ber_len_t len = 0;
int rc = LDAP_SUCCESS;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_get_dn_ber\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n", 0, 0, 0 );
-#endif
assert( ld != NULL );
assert( LDAP_VALID(ld) );
{
char *out = NULL;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2ufn\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
-#endif
( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
&out, LDAP_DN_FORMAT_UFN );
int iRDN;
unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_explode_dn\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
-#endif
if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP )
!= LDAP_SUCCESS ) {
const char *p;
int iAVA;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_explode_rdn\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
-#endif
/*
* we only parse the first rdn
{
char *out = NULL;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2dcedn\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
-#endif
( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
&out, LDAP_DN_FORMAT_DCE );
{
char *out = NULL;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_dcedn2dn\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
-#endif
( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 );
{
char *out = NULL;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2ad_canonical\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 );
-#endif
( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
&out, LDAP_DN_FORMAT_AD_CANONICAL );
* from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK )
*
* fin can be one of:
- * LDAP_DN_FORMAT_LDAP (rfc 2253 and ldapbis liberal,
- * plus some rfc 1779)
- * LDAP_DN_FORMAT_LDAPV3 (rfc 2253 and ldapbis)
- * LDAP_DN_FORMAT_LDAPV2 (rfc 1779)
+ * LDAP_DN_FORMAT_LDAP (RFC 4514 liberal, plus some RFC 1779)
+ * LDAP_DN_FORMAT_LDAPV3 (RFC 4514)
+ * LDAP_DN_FORMAT_LDAPV2 (RFC 1779)
* LDAP_DN_FORMAT_DCE (?)
*
* fout can be any of the above except
* LDAP_DN_FORMAT_LDAP
* plus:
- * LDAP_DN_FORMAT_UFN (rfc 1781, partial and with extensions)
+ * LDAP_DN_FORMAT_UFN (RFC 1781, partial and with extensions)
* LDAP_DN_FORMAT_AD_CANONICAL (?)
*/
int
int rc;
LDAPDN tmpDN = NULL;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_dn_normalize\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n", 0, 0, 0 );
-#endif
- assert( dnout );
+ assert( dnout != NULL );
*dnout = NULL;
#define LDAP_DN_ESCAPE(c) ( (c) == '\\' )
#define LDAP_DN_VALUE_END(c) \
( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) )
+
+/* NOTE: according to RFC 4514, '=' can be escaped and treated as special,
+ * i.e. escaped both as "\<hexpair>" and * as "\=", but it is treated as
+ * a regular char, i.e. it can also appear as '='.
+ *
+ * As such, in 2.2 we used to allow reading unescaped '=', but we always
+ * produced escaped '\3D'; this changes since 2.3, if compatibility issues
+ * do not arise
+ */
#define LDAP_DN_NE(c) \
( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
- || LDAP_DN_AVA_EQUALS(c) || LDAP_DN_QUOTES(c) \
+ || LDAP_DN_QUOTES(c) \
|| (c) == '<' || (c) == '>' )
#define LDAP_DN_MAYESCAPE(c) \
( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \
+ || LDAP_DN_AVA_EQUALS(c) \
|| LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) )
+#define LDAP_DN_SHOULDESCAPE(c) ( LDAP_DN_AVA_EQUALS(c) )
+
#define LDAP_DN_NEEDESCAPE(c) \
( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
#define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c)
* LDAPAVA helpers (will become part of the API for operations
* on structural representations of DNs).
*/
-LDAPAVA *
+static LDAPAVA *
ldapava_new( const struct berval *attr, const struct berval *val,
unsigned flags, void *ctx )
{
LDAPAVA *ava;
- assert( attr );
- assert( val );
+ assert( attr != NULL );
+ assert( val != NULL );
ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx );
void
ldapava_free( LDAPAVA *ava, void *ctx )
{
- assert( ava );
+ assert( ava != NULL );
#if 0
/* ava's private must be freed by caller
{
struct berval bv;
- assert( str );
+ assert( str != NULL );
bv.bv_len = strlen( str );
bv.bv_val = (char *) str;
char *str, *end;
struct berval bvtmp, *bv = &bvtmp;
- assert( bvin );
- assert( bvin->bv_val );
- assert( dn );
+ assert( bvin != NULL );
+ assert( bvin->bv_val != NULL );
+ assert( dn != NULL );
*bv = *bvin;
str = bv->bv_val;
end = str + bv->bv_len;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ARGS, "ldap_bv2dn(%s,%u)\n%s", str, flags, "" );
-#else
- Debug( LDAP_DEBUG_TRACE, "=> ldap_bv2dn(%s,%u)\n%s", str, flags, "" );
-#endif
+ Debug( LDAP_DEBUG_ARGS, "=> ldap_bv2dn(%s,%u)\n", str, flags, 0 );
*dn = NULL;
LDAP_FREEX( tmpDN, ctx );
}
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS, "<= ldap_bv2dn(%s,%u)=%d\n",
- str, flags, rc );
-#else
- Debug( LDAP_DEBUG_TRACE, "<= ldap_bv2dn(%s,%u)=%d\n", str, flags, rc );
-#endif
+ Debug( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc,
+ rc ? ldap_err2string( rc ) : "" );
*dn = newDN;
return( rc );
{
struct berval bv;
- assert( str );
+ assert( str != NULL );
assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */
bv.bv_len = strlen( str );
char *str;
ber_len_t stoplen;
- assert( bv );
- assert( bv->bv_len );
- assert( bv->bv_val );
+ assert( bv != NULL );
+ assert( bv->bv_len != 0 );
+ assert( bv->bv_val != NULL );
assert( rdn || flags & LDAP_DN_SKIP );
- assert( n );
+ assert( n != NULL );
str = bv->bv_val;
stoplen = bv->bv_len;
* an AttributeType can be encoded as:
* - its string representation; in detail, implementations
* MUST recognize AttributeType string type names listed
- * in section 2.3 of draft-ietf-ldapbis-dn-XX.txt, and
- * MAY recognize other names.
- * - its numeric OID (a dotted decimal string); in detail
- * RFC 2253 asserts that ``Implementations MUST allow
- * an oid in the attribute type to be prefixed by one
- * of the character strings "oid." or "OID."''. As soon
- * as draft-ietf-ldapbis-dn-XX.txt obsoletes RFC 2253
- * I'm not sure whether this is required or not any
- * longer; to be liberal, we still implement it.
+ * in Section 3 of RFC 4514, and MAY recognize other names.
+ * - its numeric OID (a dotted decimal string)
*/
case B4AVA:
if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) {
/*
- * RFC 2253 does not explicitly
- * allow lang extensions to attribute
- * types in DNs ...
+ * RFC 4514 explicitly does not allow attribute
+ * description options, such as language tags.
*/
if ( flags & LDAP_DN_PEDANTIC ) {
goto parsing_error;
}
/*
- * here STRING means RFC 2253 string
+ * here STRING means RFC 4514 string
* FIXME: what about DCE strings?
*/
if ( !p[ 0 ] ) {
const char *p, *end, *startPos, *endPos = NULL;
ber_len_t len, escapes;
- assert( str );
- assert( val );
- assert( next );
+ assert( str != NULL );
+ assert( val != NULL );
+ assert( next != NULL );
*next = NULL;
end = str + stoplen;
*/
return( 1 );
- } else if (!LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
+ } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
if ( p[ 0 ] == '\0' ) {
return( 1 );
}
const char *p, *startPos, *endPos = NULL;
ber_len_t len, escapes;
- assert( str );
- assert( val );
- assert( next );
+ assert( str != NULL );
+ assert( val != NULL );
+ assert( next != NULL );
*next = NULL;
const char *p, *startPos, *endPos = NULL;
ber_len_t len, escapes;
- assert( str );
- assert( val );
- assert( next );
+ assert( str != NULL );
+ assert( val != NULL );
+ assert( next != NULL );
*next = NULL;
ber_len_t len;
unsigned escapes = 0;
- assert( str );
- assert( val );
- assert( next );
+ assert( str != NULL );
+ assert( val != NULL );
+ assert( next != NULL );
*next = NULL;
{
char c1, c2;
- assert( str );
- assert( c );
+ assert( str != NULL );
+ assert( c != NULL );
c1 = str[ 0 ];
c2 = str[ 1 ];
ber_len_t len;
ber_len_t s, d;
- assert( str );
- assert( val );
- assert( next );
+ assert( str != NULL );
+ assert( val != NULL );
+ assert( next != NULL );
*next = NULL;
{
static const char hexdig[] = "0123456789ABCDEF";
- assert( val );
- assert( pair );
+ assert( val != NULL );
+ assert( pair != NULL );
/*
* we assume the string has enough room for the hex encoding
{
ber_len_t s, d;
- assert( val );
- assert( str );
+ assert( val != NULL );
+ assert( str != NULL );
if ( val->bv_len == 0 ) {
return( 0 );
strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
{
ber_len_t l, cl = 1;
- char *p;
+ char *p, *end;
int escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3;
#ifdef PRETTY_ESCAPE
int escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3;
#endif /* PRETTY_ESCAPE */
- assert( val );
- assert( len );
+ assert( val != NULL );
+ assert( len != NULL );
*len = 0;
if ( val->bv_len == 0 ) {
return( 0 );
}
- for ( l = 0, p = val->bv_val; p < val->bv_val + val->bv_len; p += cl ) {
+ end = val->bv_val + val->bv_len - 1;
+ for ( l = 0, p = val->bv_val; p <= end; p += cl ) {
/*
* escape '%x00'
l += escaped_byte_len * cl;
} else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
+ || LDAP_DN_SHOULDESCAPE( p[ 0 ] )
|| ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
- || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
+ || ( p == end && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
#ifdef PRETTY_ESCAPE
#if 0
if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) {
{
ber_len_t s, d, end;
- assert( val );
- assert( str );
- assert( len );
+ assert( val != NULL );
+ assert( str != NULL );
+ assert( len != NULL );
if ( val->bv_len == 0 ) {
*len = 0;
/*
* The length was checked in strval2strlen();
- * LDAP_UTF8_CHARLEN() should suffice
*/
- cl = LDAP_UTF8_CHARLEN2( &val->bv_val[ s ], cl );
- assert( cl > 0 );
+ cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] );
/*
* there might be some chars we want to escape in form
#endif
#else /* ! PRETTY_ESCAPE */
|| LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
+ || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
|| ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
} else {
#ifdef PRETTY_ESCAPE
if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
+ || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
|| ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
str[ d++ ] = '\\';
ber_len_t l;
char *p;
- assert( val );
- assert( len );
+ assert( val != NULL );
+ assert( len != NULL );
*len = 0;
if ( val->bv_len == 0 ) {
} else {
for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
+ || LDAP_DN_SHOULDESCAPE( p[ 0 ] )
|| ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
|| ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
l += 2;
{
ber_len_t s, d, end;
- assert( val );
- assert( str );
- assert( len );
+ assert( val != NULL );
+ assert( str != NULL );
+ assert( len != NULL );
if ( val->bv_len == 0 ) {
*len = 0;
for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
+ || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
|| ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
str[ d++ ] = '\\';
ber_len_t l;
char *p;
- assert( val );
- assert( len );
+ assert( val != NULL );
+ assert( len != NULL );
*len = 0;
if ( val->bv_len == 0 ) {
{
ber_len_t s, d;
- assert( val );
- assert( str );
- assert( len );
+ assert( val != NULL );
+ assert( str != NULL );
+ assert( len != NULL );
if ( val->bv_len == 0 ) {
*len = 0;
/*
* Length of the (supposedly) AD canonical string representation,
- * accounting for escaped hex of UTF-8 chars
+ * accounting for chars that need to be escaped
*/
static int
strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
{
- ber_len_t l;
+ ber_len_t l, cl;
char *p;
- assert( val );
- assert( len );
+ assert( val != NULL );
+ assert( len != NULL );
*len = 0;
if ( val->bv_len == 0 ) {
return( 0 );
}
- if ( flags & LDAP_AVA_NONPRINTABLE ) {
- /*
- * FIXME: Turn the value into a binary encoded BER?
- */
- return( -1 );
-
- } else {
- for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
- if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
- l += 2;
-
- } else {
- l++;
- }
+ for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
+ cl = LDAP_UTF8_CHARLEN2( p, cl );
+ if ( cl == 0 ) {
+ /* illegal utf-8 char */
+ return -1;
+ } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
+ l += 2;
+ } else {
+ l += cl;
}
}
*len = l;
-
+
return( 0 );
}
/*
- * convert to (supposedly) AD string representation,
- * escaping with hex the UTF-8 stuff;
+ * convert to (supposedly) AD string representation,
* assume the destination has enough room for escaping
*/
static int
strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
{
- ber_len_t s, d;
+ ber_len_t s, d, cl;
- assert( val );
- assert( str );
- assert( len );
+ assert( val != NULL );
+ assert( str != NULL );
+ assert( len != NULL );
if ( val->bv_len == 0 ) {
*len = 0;
return( 0 );
}
- if ( flags & LDAP_AVA_NONPRINTABLE ) {
- /*
- * FIXME: Turn the value into a binary encoded BER?
- */
- *len = 0;
- return( -1 );
-
- } else {
-
- /*
- * we assume the string has enough room for the hex encoding
- * of the value
- */
+ /*
+ * we assume the string has enough room for the escaping
+ * of the value
+ */
- for ( s = 0, d = 0; s < val->bv_len; ) {
- if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) {
- str[ d++ ] = '\\';
- }
+ for ( s = 0, d = 0; s < val->bv_len; ) {
+ cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl );
+ if ( cl == 0 ) {
+ /* illegal utf-8 char */
+ return -1;
+ } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) {
+ str[ d++ ] = '\\';
+ }
+ for (; cl--;) {
str[ d++ ] = val->bv_val[ s++ ];
}
}
/* we are guaranteed there's enough memory in str */
/* sanity */
- assert( dn );
- assert( bv );
- assert( iRDN );
+ assert( dn != NULL );
+ assert( bv != NULL );
+ assert( iRDN != NULL );
assert( *iRDN >= 0 );
str = bv->bv_val + pos;
LDAPRDN rdn;
LDAPAVA *ava;
- assert( dn[ i ] );
+ assert( dn[ i ] != NULL );
rdn = dn[ i ];
- assert( rdn[ 0 ] );
+ assert( rdn[ 0 ] != NULL );
ava = rdn[ 0 ];
if ( !LDAP_DN_IS_RDN_DC( rdn ) ) {
int iAVA;
ber_len_t l = 0;
- assert( rdn );
- assert( len );
+ assert( rdn != NULL );
+ assert( len != NULL );
*len = 0;
int iAVA;
ber_len_t l = 0;
- assert( rdn );
- assert( len );
+ assert( rdn != NULL );
+ assert( len != NULL );
*len = 0;
struct berval bv;
int rc;
- assert( str );
+ assert( str != NULL );
if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
return LDAP_PARAM_ERROR;
int rc, back;
ber_len_t l;
- assert( bv );
+ assert( bv != NULL );
bv->bv_len = 0;
bv->bv_val = NULL;
struct berval bv;
int rc;
- assert( str );
+ assert( str != NULL );
if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
return LDAP_PARAM_ERROR;
int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l );
int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l );
- assert( bv );
+ assert( bv != NULL );
bv->bv_len = 0;
bv->bv_val = NULL;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ARGS, "=> ldap_dn2bv(%u)\n%s%s",
- flags, "", "" );
-#else
- Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2bv(%u)\n%s%s", flags, "", "" );
-#endif
+ Debug( LDAP_DEBUG_ARGS, "=> ldap_dn2bv(%u)\n", flags, 0, 0 );
/*
* a null dn means an empty dn string
return LDAP_PARAM_ERROR;
}
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, RESULTS, "<= ldap_dn2bv(%s,%u)=%d\n",
- bv->bv_val, flags, rc );
-#else
- Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s,%u)=%d\n",
- bv->bv_val, flags, rc );
-#endif
+ Debug( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n",
+ bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" );
return_results:;
return( rc );
}
-#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 = NULL;
- void *ptrs[2048];
- int i, j, k = 0, navas, nrdns, rc = LDAP_SUCCESS;
- int set = -1;
- 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(LDAPRDN) * (nrdns+1);
- dnsize += 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[nrdns] = NULL;
- newRDN = (LDAPRDN)(newDN + nrdns+1);
- newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
- 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[k] = NULL;
- newRDN += k+1;
- }
- newDN[j++] = newRDN;
-
- k = 0;
- set = ne->set;
- }
- newAVA->la_private = NULL;
- newAVA->la_flags = LDAP_AVA_STRING;
-
- 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 );
-#ifdef HAVE_EBCDIC
- newAVA->la_attr.bv_val = LDAP_STRDUP( newAVA->la_attr.bv_val );
- __etoa( newAVA->la_attr.bv_val );
- newAVA->la_flags |= LDAP_AVA_FREE_ATTR;
-#endif
- } else {
-get_oid: newAVA->la_attr.bv_val = oidptr;
- newAVA->la_attr.bv_len = OBJ_obj2txt( oidptr, oidrem, obj, 1 );
-#ifdef HAVE_EBCDIC
- __etoa( newAVA->la_attr.bv_val );
-#endif
- 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 = (char *) 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 );
- newAVA->la_flags |= LDAP_AVA_FREE_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 */
- newAVA->la_value = Val;
- default:
- ;
- }
- newRDN[k] = newAVA;
- newAVA++;
- k++;
- }
- newRDN[k] = NULL;
-
- if ( func ) {
- rc = func( newDN, flags, NULL );
- if ( rc != LDAP_SUCCESS )
- goto nomem;
- }
-
- rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
-
-nomem:
- for (;baseAVA < newAVA; baseAVA++) {
- if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
- LDAP_FREE( baseAVA->la_attr.bv_val );
- if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
- 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 */
-