int dnPretty( Syntax *syntax, struct berval *val, struct berval *out, void *ctx) { assert( val != NULL ); assert( out != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len == 0 ) { ber_dupbv_x( out, val, ctx ); } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { return LDAP_INVALID_SYNTAX; } else { LDAPDN dn = NULL; int rc; /* FIXME: should be liberal in what we accept */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } /* FIXME: not sure why the default isn't pretty */ /* RE: the default is the form that is used as * an internal representation; the pretty form * is a variant */ rc = ldap_dn2bv_x( dn, out, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 ); return LDAP_SUCCESS; }
int dnNormalize( slap_mask_t use, Syntax *syntax, MatchingRule *mr, struct berval *val, struct berval *out, void *ctx) { assert( val != NULL ); assert( out != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len != 0 ) { LDAPDN dn = NULL; int rc; /* * Go to structural representation */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } /* * Back to string representation */ rc = ldap_dn2bv_x( dn, out, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } else { ber_dupbv_x( out, val, ctx ); } Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 ); return LDAP_SUCCESS; }
/* * Combination of both dnPretty and dnNormalize */ int dnPrettyNormal( Syntax *syntax, struct berval *val, struct berval *pretty, struct berval *normal, void *ctx) { assert( val != NULL ); assert( pretty != NULL ); assert( normal != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len == 0 ) { ber_dupbv_x( pretty, val, ctx ); ber_dupbv_x( normal, val, ctx ); } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { /* too big */ return LDAP_INVALID_SYNTAX; } else { LDAPDN dn = NULL; int rc; pretty->bv_val = NULL; normal->bv_val = NULL; pretty->bv_len = 0; normal->bv_len = 0; /* FIXME: should be liberal in what we accept */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } rc = ldap_dn2bv_x( dn, pretty, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); if ( rc != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); ber_memfree_x( pretty->bv_val, ctx ); pretty->bv_val = NULL; pretty->bv_len = 0; return LDAP_INVALID_SYNTAX; } rc = ldap_dn2bv_x( dn, normal, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { ber_memfree_x( pretty->bv_val, ctx ); pretty->bv_val = NULL; pretty->bv_len = 0; return LDAP_INVALID_SYNTAX; } } Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n", pretty->bv_val ? pretty->bv_val : "", normal->bv_val ? normal->bv_val : "", 0 ); return LDAP_SUCCESS; }
/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN. * x509_name must be raw DER. 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 from a hardcoded table. */ int ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func, unsigned flags ) { LDAPDN newDN; LDAPRDN newRDN; LDAPAVA *newAVA, *baseAVA; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; char oids[8192], *oidptr = oids, *oidbuf = NULL; void *ptrs[2048]; char *dn_end, *rdn_end; int i, navas, nrdns, rc = LDAP_SUCCESS; size_t dnsize, oidrem = sizeof(oids), oidsize = 0; int csize; ber_tag_t tag; ber_len_t len; oid_name *oidname; struct berval Oid, Val, oid2, *in = x509_name; assert( bv != NULL ); bv->bv_len = 0; bv->bv_val = NULL; navas = 0; nrdns = 0; /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs. * An AVA is a SEQUENCE of attr and value. * Count the number of AVAs and RDNs */ ber_init2( ber, in, LBER_USE_DER ); tag = ber_peek_tag( ber, &len ); if ( tag != LBER_SEQUENCE ) return LDAP_DECODING_ERROR; for ( tag = ber_first_element( ber, &len, &dn_end ); tag == LBER_SET; tag = ber_next_element( ber, &len, dn_end )) { nrdns++; for ( tag = ber_first_element( ber, &len, &rdn_end ); tag == LBER_SEQUENCE; tag = ber_next_element( ber, &len, rdn_end )) { tag = ber_skip_tag( ber, &len ); ber_skip_data( ber, len ); navas++; } } /* 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)(char *)ptrs; } newDN[nrdns] = NULL; newRDN = (LDAPRDN)(newDN + nrdns+1); newAVA = (LDAPAVA *)(newRDN + navas + nrdns); baseAVA = newAVA; /* Rewind and start extracting */ ber_rewind( ber ); tag = ber_first_element( ber, &len, &dn_end ); for ( i = nrdns - 1; i >= 0; i-- ) { newDN[i] = newRDN; for ( tag = ber_first_element( ber, &len, &rdn_end ); tag == LBER_SEQUENCE; tag = ber_next_element( ber, &len, rdn_end )) { *newRDN++ = newAVA; tag = ber_skip_tag( ber, &len ); tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM ); if ( tag != LBER_TAG_OID ) { rc = LDAP_DECODING_ERROR; goto nomem; } oid2.bv_val = oidptr; oid2.bv_len = oidrem; if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) { rc = LDAP_DECODING_ERROR; goto nomem; } oidname = find_oid( &oid2 ); if ( !oidname ) { newAVA->la_attr = oid2; oidptr += oid2.bv_len + 1; oidrem -= oid2.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; } } } else { if ( func ) { newAVA->la_attr = oidname->oid; } else { newAVA->la_attr = oidname->name; } } newAVA->la_private = NULL; newAVA->la_flags = LDAP_AVA_STRING; tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM ); switch(tag) { case LBER_TAG_UNIVERSAL: /* This uses 32-bit ISO 10646-1 */ csize = 4; goto to_utf8; case LBER_TAG_BMP: /* This uses 16-bit ISO 10646-1 */ csize = 2; goto to_utf8; case LBER_TAG_TELETEX: /* 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_NONPRINTABLE; allocd: newAVA->la_flags |= LDAP_AVA_FREE_VALUE; if (rc != LDAP_SUCCESS) goto nomem; break; case LBER_TAG_UTF8: newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; /* This is already in UTF-8 encoding */ case LBER_TAG_IA5: case LBER_TAG_PRINTABLE: /* These are always 7-bit strings */ newAVA->la_value = Val; break; case LBER_BITSTRING: /* X.690 bitString value converted to RFC4517 Bit String */ rc = der_to_ldap_BitString( &Val, &newAVA->la_value ); goto allocd; default: /* Not a string type at all */ newAVA->la_flags = 0; newAVA->la_value = Val; break; } newAVA++; } *newRDN++ = NULL; tag = ber_next_element( ber, &len, dn_end ); } 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)(char *) ptrs ) LDAP_FREE( newDN ); return rc; }