From: Howard Chu Date: Thu, 18 Apr 2002 12:29:30 +0000 (+0000) Subject: Added ldap_X509dn2bv() X-Git-Tag: OPENLDAP_REL_ENG_2_MP~170 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=17ae956518e4b011eb423f63fd1fd93402d0cf5c;p=openldap Added ldap_X509dn2bv() deleted ldap_pvt_tls_get_peer() changed ldap_pvt_tls_get_peer_dn() to use ldap_X509dn2bv() added ldap_pvt_tls_get_my_dn() --- diff --git a/include/ldap.h b/include/ldap.h index 25b5294626..0332f88597 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -1273,6 +1273,12 @@ ldap_explode_rdn LDAP_P(( /* deprecated */ LDAP_CONST char *rdn, int notypes )); +typedef int LDAPDN_rewrite_func LDAP_P(( LDAPDN *dn, unsigned flags )); + +LDAP_F( int ) +ldap_X509dn2bv LDAP_P(( void *x509_name, struct berval *dn, + LDAPDN_rewrite_func *func, unsigned flags )); + LDAP_F( char * ) ldap_dn2dcedn LDAP_P(( LDAP_CONST char *dn )); /* deprecated */ diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 8a794e6f05..d1d73eba21 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -179,8 +179,12 @@ LDAP_F (void *) ldap_pvt_tls_sb_ctx LDAP_P(( Sockbuf *sb )); LDAP_F (int) ldap_pvt_tls_init_default_ctx LDAP_P(( void )); -LDAP_F (char *) ldap_pvt_tls_get_peer LDAP_P(( void *ctx )); -LDAP_F (char *) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx )); +typedef int LDAPDN_rewrite_dummy LDAP_P (( void *dn, unsigned flags )); + +LDAP_F (char *) ldap_pvt_tls_get_my_dn LDAP_P(( void *ctx, + LDAPDN_rewrite_dummy *func, unsigned flags )); +LDAP_F (char *) ldap_pvt_tls_get_peer_dn LDAP_P(( void *ctx, + LDAPDN_rewrite_dummy *func, unsigned flags )); LDAP_F (int) ldap_pvt_tls_get_strength LDAP_P(( void *ctx )); LDAP_END_DECL diff --git a/libraries/libldap/getdn.c b/libraries/libldap/getdn.c index db9fdb9083..df8ecf7cad 100644 --- a/libraries/libldap/getdn.c +++ b/libraries/libldap/getdn.c @@ -3291,3 +3291,108 @@ return_results:; return( rc ); } +#ifdef HAVE_TLS +#include +#include + +/* 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 = NULL; + LDAPRDN *newRDN = NULL; + X509_NAME_ENTRY *ne; + ASN1_OBJECT *obj; + ASN1_STRING *str; + char oidbuf[2048]; + int i, j, nrdns, rc = LDAP_NO_MEMORY; + + struct berval Type; + struct berval Val; + + assert( bv ); + bv->bv_len = 0; + bv->bv_val = NULL; + + nrdns = X509_NAME_entry_count( x509_name ); + newDN = (LDAPDN *)LDAP_MALLOC( sizeof(LDAPDN) + sizeof(LDAPRDN *) + * (nrdns+1) ); + if ( newDN == NULL ) + return LDAP_NO_MEMORY; + + newDN[0] = (LDAPRDN**)(newDN+1); + + /* Retrieve RDNs in reverse order; LDAP is backwards from X.500. + * The OpenSSL library appears to allow only 1 AVA per RDN. + */ + for ( i = nrdns - 1, j = 0; i >= 0; i--, j++ ) { + newDN[0][j] = NULL; + ne = X509_NAME_get_entry( x509_name, i ); + obj = X509_NAME_ENTRY_get_object( ne ); + str = X509_NAME_ENTRY_get_data( ne ); + + if ( !func ) { + int n = OBJ_obj2nid( obj ); + + if (n == NID_undef) + goto get_oid; + Type.bv_val = (char *)OBJ_nid2sn( n ); + Type.bv_len = strlen( Type.bv_val ); + } else { +get_oid: Type.bv_val = oidbuf; + Type.bv_len = OBJ_obj2txt( oidbuf, sizeof( oidbuf ), obj, 1 ); + } + Val.bv_len = str->length; + Val.bv_val = str->data; + + newRDN = (LDAPRDN *)LDAP_MALLOC( sizeof(LDAPRDN) + sizeof(LDAPAVA *) * 2); + if ( newRDN == NULL ) + goto nomem; + + newRDN[0] = (LDAPAVA**)(newRDN+1); + newRDN[0][0] = ldapava_new( &Type, &Val, LDAP_AVA_STRING ); + if ( newRDN[0][0] == NULL ) + goto nomem; + + newRDN[0][1] = NULL; + newDN[0][j] = newRDN; + newRDN = NULL; + } + newDN[0][j] = NULL; + + if ( func ) { + rc = func( newDN, flags ); + if ( rc != LDAP_SUCCESS ) + goto nomem; + } + + rc = ldap_dn2bv( newDN, bv, LDAP_DN_FORMAT_LDAPV3 ); + ldap_dnfree( newDN ); + + return rc; + +nomem: + if ( newRDN ) + LDAP_FREE( newRDN ); + if ( newDN ) + ldap_dnfree( newDN ); + return rc; +} +#endif /* HAVE_TLS */ + diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index 7fcb778c11..3fc57af14a 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -788,6 +788,23 @@ ldap_pvt_tls_get_strength( void *s ) } +char * +ldap_pvt_tls_get_my_dn( void *s, LDAPDN_rewrite_dummy *func, unsigned flags ) +{ + X509 *x; + X509_NAME *xn; + struct berval dn; + + x = SSL_get_certificate((SSL *)s); + + if (!x) return NULL; + + xn = X509_get_subject_name(x); + ldap_X509dn2bv(xn, &dn, (LDAPDN_rewrite_func *)func, flags ); + X509_free(x); + return dn.bv_val; +} + static X509 * tls_get_cert( SSL *s ) { @@ -803,42 +820,20 @@ tls_get_cert( SSL *s ) } char * -ldap_pvt_tls_get_peer( void *s ) -{ - X509 *x; - X509_NAME *xn; - char buf[2048], *p; - - - x = tls_get_cert((SSL *)s); - - if (!x) - return NULL; - - xn = X509_get_subject_name(x); - p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf))); - X509_free(x); - return p; -} - -char * -ldap_pvt_tls_get_peer_dn( void *s ) +ldap_pvt_tls_get_peer_dn( void *s, LDAPDN_rewrite_dummy *func, unsigned flags ) { X509 *x; X509_NAME *xn; - char buf[2048], *p, *dn; + struct berval dn; x = tls_get_cert((SSL *)s); if (!x) return NULL; xn = X509_get_subject_name(x); - p = X509_NAME_oneline(xn, buf, sizeof(buf)); - - dn = ldap_dcedn2dn( p ); - + ldap_X509dn2bv(xn, &dn, (LDAPDN_rewrite_func *)func, flags); X509_free(x); - return dn; + return dn.bv_val; } char * @@ -983,7 +978,7 @@ ldap_pvt_tls_check_hostname( void *s, const char *name_in ) const char * ldap_pvt_tls_get_peer_issuer( void *s ) { -#if 0 /* currently unused; see ldap_pvt_tls_get_peer() if needed */ +#if 0 /* currently unused; see ldap_pvt_tls_get_peer_dn() if needed */ X509 *x; X509_NAME *xn; char buf[2048], *p; @@ -1256,7 +1251,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) /* we need to let SASL know */ ssf = ldap_pvt_tls_get_strength( ssl ); - authid = ldap_pvt_tls_get_peer( ssl ); + authid = ldap_pvt_tls_get_my_dn( ssl, NULL, 0 ); (void) ldap_int_sasl_external( ld, conn, authid, ssf ); }