Back to index

openldap  2.4.31
tls2.c
Go to the documentation of this file.
00001 /* tls.c - Handle tls/ssl. */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* ACKNOWLEDGEMENTS: restructured by Howard Chu.
00017  */
00018 
00019 #include "portable.h"
00020 #include "ldap_config.h"
00021 
00022 #include <stdio.h>
00023 
00024 #include <ac/stdlib.h>
00025 #include <ac/errno.h>
00026 #include <ac/socket.h>
00027 #include <ac/string.h>
00028 #include <ac/ctype.h>
00029 #include <ac/time.h>
00030 #include <ac/unistd.h>
00031 #include <ac/param.h>
00032 #include <ac/dirent.h>
00033 
00034 #include "ldap-int.h"
00035 
00036 #ifdef HAVE_TLS
00037 
00038 #include "ldap-tls.h"
00039 
00040 static tls_impl *tls_imp = &ldap_int_tls_impl;
00041 #define HAS_TLS( sb )       ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
00042                             (void *)tls_imp->ti_sbio )
00043 
00044 #endif /* HAVE_TLS */
00045 
00046 /* RFC2459 minimum required set of supported attribute types
00047  * in a certificate DN
00048  */
00049 typedef struct oid_name {
00050        struct berval oid;
00051        struct berval name;
00052 } oid_name;
00053 
00054 static oid_name oids[] = {
00055        { BER_BVC("2.5.4.3"), BER_BVC("cn") },
00056        { BER_BVC("2.5.4.4"), BER_BVC("sn") },
00057        { BER_BVC("2.5.4.6"), BER_BVC("c") },
00058        { BER_BVC("2.5.4.7"), BER_BVC("l") },
00059        { BER_BVC("2.5.4.8"), BER_BVC("st") },
00060        { BER_BVC("2.5.4.10"), BER_BVC("o") },
00061        { BER_BVC("2.5.4.11"), BER_BVC("ou") },
00062        { BER_BVC("2.5.4.12"), BER_BVC("title") },
00063        { BER_BVC("2.5.4.41"), BER_BVC("name") },
00064        { BER_BVC("2.5.4.42"), BER_BVC("givenName") },
00065        { BER_BVC("2.5.4.43"), BER_BVC("initials") },
00066        { BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") },
00067        { BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") },
00068        { BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") },
00069        { BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") },
00070        { BER_BVNULL, BER_BVNULL }
00071 };
00072 
00073 #ifdef HAVE_TLS
00074 
00075 void
00076 ldap_pvt_tls_ctx_free ( void *c )
00077 {
00078        if ( !c ) return;
00079        tls_imp->ti_ctx_free( c );
00080 }
00081 
00082 static void
00083 tls_ctx_ref( tls_ctx *ctx )
00084 {
00085        if ( !ctx ) return;
00086 
00087        tls_imp->ti_ctx_ref( ctx );
00088 }
00089 
00090 #ifdef LDAP_R_COMPILE
00091 /*
00092  * an extra mutex for the default ctx.
00093  */
00094 static ldap_pvt_thread_mutex_t tls_def_ctx_mutex;
00095 #endif
00096 
00097 void
00098 ldap_int_tls_destroy( struct ldapoptions *lo )
00099 {
00100        if ( lo->ldo_tls_ctx ) {
00101               ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
00102               lo->ldo_tls_ctx = NULL;
00103        }
00104 
00105        if ( lo->ldo_tls_certfile ) {
00106               LDAP_FREE( lo->ldo_tls_certfile );
00107               lo->ldo_tls_certfile = NULL;
00108        }
00109        if ( lo->ldo_tls_keyfile ) {
00110               LDAP_FREE( lo->ldo_tls_keyfile );
00111               lo->ldo_tls_keyfile = NULL;
00112        }
00113        if ( lo->ldo_tls_dhfile ) {
00114               LDAP_FREE( lo->ldo_tls_dhfile );
00115               lo->ldo_tls_dhfile = NULL;
00116        }
00117        if ( lo->ldo_tls_cacertfile ) {
00118               LDAP_FREE( lo->ldo_tls_cacertfile );
00119               lo->ldo_tls_cacertfile = NULL;
00120        }
00121        if ( lo->ldo_tls_cacertdir ) {
00122               LDAP_FREE( lo->ldo_tls_cacertdir );
00123               lo->ldo_tls_cacertdir = NULL;
00124        }
00125        if ( lo->ldo_tls_ciphersuite ) {
00126               LDAP_FREE( lo->ldo_tls_ciphersuite );
00127               lo->ldo_tls_ciphersuite = NULL;
00128        }
00129        if ( lo->ldo_tls_crlfile ) {
00130               LDAP_FREE( lo->ldo_tls_crlfile );
00131               lo->ldo_tls_crlfile = NULL;
00132        }
00133 }
00134 
00135 /*
00136  * Tear down the TLS subsystem. Should only be called once.
00137  */
00138 void
00139 ldap_pvt_tls_destroy( void )
00140 {
00141        struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();   
00142 
00143        ldap_int_tls_destroy( lo );
00144 
00145        tls_imp->ti_tls_destroy();
00146 }
00147 
00148 /*
00149  * Initialize a particular TLS implementation.
00150  * Called once per implementation.
00151  */
00152 static int
00153 tls_init(tls_impl *impl )
00154 {
00155        static int tls_initialized = 0;
00156 
00157        if ( !tls_initialized++ ) {
00158 #ifdef LDAP_R_COMPILE
00159               ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
00160 #endif
00161        }
00162 
00163        if ( impl->ti_inited++ ) return 0;
00164 
00165 #ifdef LDAP_R_COMPILE
00166        impl->ti_thr_init();
00167 #endif
00168        return impl->ti_tls_init();
00169 }
00170 
00171 /*
00172  * Initialize TLS subsystem. Called once per implementation.
00173  */
00174 int
00175 ldap_pvt_tls_init( void )
00176 {
00177        return tls_init( tls_imp );
00178 }
00179 
00180 /*
00181  * initialize a new TLS context
00182  */
00183 static int
00184 ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
00185 {
00186        int rc = 0;
00187        tls_impl *ti = tls_imp;
00188        struct ldaptls lts = lo->ldo_tls_info;
00189 
00190        if ( lo->ldo_tls_ctx )
00191               return 0;
00192 
00193        tls_init( ti );
00194 
00195        if ( is_server && !lts.lt_certfile && !lts.lt_keyfile &&
00196               !lts.lt_cacertfile && !lts.lt_cacertdir ) {
00197               /* minimum configuration not provided */
00198               return LDAP_NOT_SUPPORTED;
00199        }
00200 
00201 #ifdef HAVE_EBCDIC
00202        /* This ASCII/EBCDIC handling is a real pain! */
00203        if ( lts.lt_ciphersuite ) {
00204               lts.lt_ciphersuite = LDAP_STRDUP( lts.lt_ciphersuite );
00205               __atoe( lts.lt_ciphersuite );
00206        }
00207        if ( lts.lt_cacertfile ) {
00208               lts.lt_cacertfile = LDAP_STRDUP( lts.lt_cacertfile );
00209               __atoe( lts.lt_cacertfile );
00210        }
00211        if ( lts.lt_certfile ) {
00212               lts.lt_certfile = LDAP_STRDUP( lts.lt_certfile );
00213               __atoe( lts.lt_certfile );
00214        }
00215        if ( lts.lt_keyfile ) {
00216               lts.lt_keyfile = LDAP_STRDUP( lts.lt_keyfile );
00217               __atoe( lts.lt_keyfile );
00218        }
00219        if ( lts.lt_crlfile ) {
00220               lts.lt_crlfile = LDAP_STRDUP( lts.lt_crlfile );
00221               __atoe( lts.lt_crlfile );
00222        }
00223        if ( lts.lt_cacertdir ) {
00224               lts.lt_cacertdir = LDAP_STRDUP( lts.lt_cacertdir );
00225               __atoe( lts.lt_cacertdir );
00226        }
00227        if ( lts.lt_dhfile ) {
00228               lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile );
00229               __atoe( lts.lt_dhfile );
00230        }
00231 #endif
00232        lo->ldo_tls_ctx = ti->ti_ctx_new( lo );
00233        if ( lo->ldo_tls_ctx == NULL ) {
00234               Debug( LDAP_DEBUG_ANY,
00235                  "TLS: could not allocate default ctx.\n",
00236                      0,0,0);
00237               rc = -1;
00238               goto error_exit;
00239        }
00240 
00241        rc = ti->ti_ctx_init( lo, &lts, is_server );
00242 
00243 error_exit:
00244        if ( rc < 0 && lo->ldo_tls_ctx != NULL ) {
00245               ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
00246               lo->ldo_tls_ctx = NULL;
00247        }
00248 #ifdef HAVE_EBCDIC
00249        LDAP_FREE( lts.lt_ciphersuite );
00250        LDAP_FREE( lts.lt_cacertfile );
00251        LDAP_FREE( lts.lt_certfile );
00252        LDAP_FREE( lts.lt_keyfile );
00253        LDAP_FREE( lts.lt_crlfile );
00254        LDAP_FREE( lts.lt_cacertdir );
00255        LDAP_FREE( lts.lt_dhfile );
00256 #endif
00257        return rc;
00258 }
00259 
00260 /*
00261  * initialize the default context
00262  */
00263 int
00264 ldap_pvt_tls_init_def_ctx( int is_server )
00265 {
00266        struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();   
00267        int rc;
00268        LDAP_MUTEX_LOCK( &tls_def_ctx_mutex );
00269        rc = ldap_int_tls_init_ctx( lo, is_server );
00270        LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex );
00271        return rc;
00272 }
00273 
00274 static tls_session *
00275 alloc_handle( void *ctx_arg, int is_server )
00276 {
00277        tls_ctx       *ctx;
00278        tls_session   *ssl;
00279 
00280        if ( ctx_arg ) {
00281               ctx = ctx_arg;
00282        } else {
00283               struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT();   
00284               if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL;
00285               ctx = lo->ldo_tls_ctx;
00286        }
00287 
00288        ssl = tls_imp->ti_session_new( ctx, is_server );
00289        if ( ssl == NULL ) {
00290               Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0);
00291               return NULL;
00292        }
00293        return ssl;
00294 }
00295 
00296 static int
00297 update_flags( Sockbuf *sb, tls_session * ssl, int rc )
00298 {
00299        sb->sb_trans_needs_read  = 0;
00300        sb->sb_trans_needs_write = 0;
00301 
00302        return tls_imp->ti_session_upflags( sb, ssl, rc );
00303 }
00304 
00305 /*
00306  * Call this to do a TLS connect on a sockbuf. ctx_arg can be
00307  * a SSL_CTX * or NULL, in which case the default ctx is used.
00308  *
00309  * Return value:
00310  *
00311  *  0 - Success. Connection is ready for communication.
00312  * <0 - Error. Can't create a TLS stream.
00313  * >0 - Partial success.
00314  *       Do a select (using information from lber_pvt_sb_needs_{read,write}
00315  *            and call again.
00316  */
00317 
00318 static int
00319 ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
00320 {
00321        Sockbuf *sb = conn->lconn_sb;
00322        int    err;
00323        tls_session   *ssl = NULL;
00324 
00325        if ( HAS_TLS( sb )) {
00326               ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
00327        } else {
00328               struct ldapoptions *lo;
00329               tls_ctx *ctx;
00330 
00331               ctx = ld->ld_options.ldo_tls_ctx;
00332 
00333               ssl = alloc_handle( ctx, 0 );
00334 
00335               if ( ssl == NULL ) return -1;
00336 
00337 #ifdef LDAP_DEBUG
00338               ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
00339                      LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
00340 #endif
00341               ber_sockbuf_add_io( sb, tls_imp->ti_sbio,
00342                      LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
00343 
00344               lo = LDAP_INT_GLOBAL_OPT();   
00345               if( ctx == NULL ) {
00346                      ctx = lo->ldo_tls_ctx;
00347                      ld->ld_options.ldo_tls_ctx = ctx;
00348                      tls_ctx_ref( ctx );
00349               }
00350               if ( ld->ld_options.ldo_tls_connect_cb )
00351                      ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx,
00352                      ld->ld_options.ldo_tls_connect_arg );
00353               if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb !=
00354                      ld->ld_options.ldo_tls_connect_cb )
00355                      lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
00356        }
00357 
00358        err = tls_imp->ti_session_connect( ld, ssl );
00359 
00360 #ifdef HAVE_WINSOCK
00361        errno = WSAGetLastError();
00362 #endif
00363 
00364        if ( err < 0 )
00365        {
00366               char buf[256], *msg;
00367               if ( update_flags( sb, ssl, err )) {
00368                      return 1;
00369               }
00370 
00371               msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) );
00372               if ( msg ) {
00373                      if ( ld->ld_error ) {
00374                             LDAP_FREE( ld->ld_error );
00375                      }
00376                      ld->ld_error = LDAP_STRDUP( msg );
00377 #ifdef HAVE_EBCDIC
00378                      if ( ld->ld_error ) __etoa(ld->ld_error);
00379 #endif
00380               }
00381 
00382               Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n",
00383                      ld->ld_error ? ld->ld_error : "" ,0,0);
00384 
00385               ber_sockbuf_remove_io( sb, tls_imp->ti_sbio,
00386                      LBER_SBIOD_LEVEL_TRANSPORT );
00387 #ifdef LDAP_DEBUG
00388               ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
00389                      LBER_SBIOD_LEVEL_TRANSPORT );
00390 #endif
00391               return -1;
00392        }
00393 
00394        return 0;
00395 }
00396 
00397 /*
00398  * Call this to do a TLS accept on a sockbuf.
00399  * Everything else is the same as with tls_connect.
00400  */
00401 int
00402 ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
00403 {
00404        int    err;
00405        tls_session   *ssl = NULL;
00406 
00407        if ( HAS_TLS( sb )) {
00408               ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
00409        } else {
00410               ssl = alloc_handle( ctx_arg, 1 );
00411               if ( ssl == NULL ) return -1;
00412 
00413 #ifdef LDAP_DEBUG
00414               ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
00415                      LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
00416 #endif
00417               ber_sockbuf_add_io( sb, tls_imp->ti_sbio,
00418                      LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
00419        }
00420 
00421        err = tls_imp->ti_session_accept( ssl );
00422 
00423 #ifdef HAVE_WINSOCK
00424        errno = WSAGetLastError();
00425 #endif
00426 
00427        if ( err < 0 )
00428        {
00429               if ( update_flags( sb, ssl, err )) return 1;
00430 
00431               if ( DebugTest( LDAP_DEBUG_ANY ) ) {
00432                      char buf[256], *msg;
00433                      msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) );
00434                      Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n",
00435                             msg ? msg : "(unknown)", 0, 0 );
00436               }
00437 
00438               ber_sockbuf_remove_io( sb, tls_imp->ti_sbio,
00439                      LBER_SBIOD_LEVEL_TRANSPORT );
00440 #ifdef LDAP_DEBUG
00441               ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
00442                      LBER_SBIOD_LEVEL_TRANSPORT );
00443 #endif
00444               return -1;
00445        }
00446        return 0;
00447 }
00448 
00449 int
00450 ldap_pvt_tls_inplace ( Sockbuf *sb )
00451 {
00452        return HAS_TLS( sb ) ? 1 : 0;
00453 }
00454 
00455 int
00456 ldap_tls_inplace( LDAP *ld )
00457 {
00458        Sockbuf              *sb = NULL;
00459 
00460        if ( ld->ld_defconn && ld->ld_defconn->lconn_sb ) {
00461               sb = ld->ld_defconn->lconn_sb;
00462 
00463        } else if ( ld->ld_sb ) {
00464               sb = ld->ld_sb;
00465 
00466        } else {
00467               return 0;
00468        }
00469 
00470        return ldap_pvt_tls_inplace( sb );
00471 }
00472 
00473 int
00474 ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn,
00475        LDAPDN_rewrite_dummy *func, unsigned flags )
00476 {
00477        tls_session *session = s;
00478        struct berval bvdn;
00479        int rc;
00480 
00481        rc = tls_imp->ti_session_peer_dn( session, &bvdn );
00482        if ( rc ) return rc;
00483 
00484        rc = ldap_X509dn2bv( &bvdn, dn, 
00485                          (LDAPDN_rewrite_func *)func, flags);
00486        return rc;
00487 }
00488 
00489 int
00490 ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
00491 {
00492        tls_session *session = s;
00493 
00494        return tls_imp->ti_session_chkhost( ld, session, name_in );
00495 }
00496 
00497 int
00498 ldap_int_tls_config( LDAP *ld, int option, const char *arg )
00499 {
00500        int i;
00501 
00502        switch( option ) {
00503        case LDAP_OPT_X_TLS_CACERTFILE:
00504        case LDAP_OPT_X_TLS_CACERTDIR:
00505        case LDAP_OPT_X_TLS_CERTFILE:
00506        case LDAP_OPT_X_TLS_KEYFILE:
00507        case LDAP_OPT_X_TLS_RANDOM_FILE:
00508        case LDAP_OPT_X_TLS_CIPHER_SUITE:
00509        case LDAP_OPT_X_TLS_DHFILE:
00510        case LDAP_OPT_X_TLS_CRLFILE:       /* GnuTLS only */
00511               return ldap_pvt_tls_set_option( ld, option, (void *) arg );
00512 
00513        case LDAP_OPT_X_TLS_REQUIRE_CERT:
00514        case LDAP_OPT_X_TLS:
00515               i = -1;
00516               if ( strcasecmp( arg, "never" ) == 0 ) {
00517                      i = LDAP_OPT_X_TLS_NEVER ;
00518 
00519               } else if ( strcasecmp( arg, "demand" ) == 0 ) {
00520                      i = LDAP_OPT_X_TLS_DEMAND ;
00521 
00522               } else if ( strcasecmp( arg, "allow" ) == 0 ) {
00523                      i = LDAP_OPT_X_TLS_ALLOW ;
00524 
00525               } else if ( strcasecmp( arg, "try" ) == 0 ) {
00526                      i = LDAP_OPT_X_TLS_TRY ;
00527 
00528               } else if ( ( strcasecmp( arg, "hard" ) == 0 ) ||
00529                      ( strcasecmp( arg, "on" ) == 0 ) ||
00530                      ( strcasecmp( arg, "yes" ) == 0) ||
00531                      ( strcasecmp( arg, "true" ) == 0 ) )
00532               {
00533                      i = LDAP_OPT_X_TLS_HARD ;
00534               }
00535 
00536               if (i >= 0) {
00537                      return ldap_pvt_tls_set_option( ld, option, &i );
00538               }
00539               return -1;
00540        case LDAP_OPT_X_TLS_PROTOCOL_MIN: {
00541               char *next;
00542               long l;
00543               l = strtol( arg, &next, 10 );
00544               if ( l < 0 || l > 0xff || next == arg ||
00545                      ( *next != '\0' && *next != '.' ) )
00546                      return -1;
00547               i = l << 8;
00548               if (*next == '.') {
00549                      arg = next + 1;
00550                      l = strtol( arg, &next, 10 );
00551                      if ( l < 0 || l > 0xff || next == arg || *next != '\0' )
00552                             return -1;
00553                      i += l;
00554               }
00555               return ldap_pvt_tls_set_option( ld, option, &i );
00556               }
00557 #ifdef HAVE_OPENSSL_CRL
00558        case LDAP_OPT_X_TLS_CRLCHECK:      /* OpenSSL only */
00559               i = -1;
00560               if ( strcasecmp( arg, "none" ) == 0 ) {
00561                      i = LDAP_OPT_X_TLS_CRL_NONE ;
00562               } else if ( strcasecmp( arg, "peer" ) == 0 ) {
00563                      i = LDAP_OPT_X_TLS_CRL_PEER ;
00564               } else if ( strcasecmp( arg, "all" ) == 0 ) {
00565                      i = LDAP_OPT_X_TLS_CRL_ALL ;
00566               }
00567               if (i >= 0) {
00568                      return ldap_pvt_tls_set_option( ld, option, &i );
00569               }
00570               return -1;
00571 #endif
00572        }
00573        return -1;
00574 }
00575 
00576 int
00577 ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
00578 {
00579        struct ldapoptions *lo;
00580 
00581        if( option == LDAP_OPT_X_TLS_PACKAGE ) {
00582               *(char **)arg = LDAP_STRDUP( tls_imp->ti_name );
00583               return 0;
00584        }
00585 
00586        if( ld != NULL ) {
00587               assert( LDAP_VALID( ld ) );
00588 
00589               if( !LDAP_VALID( ld ) ) {
00590                      return LDAP_OPT_ERROR;
00591               }
00592 
00593               lo = &ld->ld_options;
00594 
00595        } else {
00596               /* Get pointer to global option structure */
00597               lo = LDAP_INT_GLOBAL_OPT();   
00598               if ( lo == NULL ) {
00599                      return LDAP_NO_MEMORY;
00600               }
00601        }
00602 
00603        switch( option ) {
00604        case LDAP_OPT_X_TLS:
00605               *(int *)arg = lo->ldo_tls_mode;
00606               break;
00607        case LDAP_OPT_X_TLS_CTX:
00608               *(void **)arg = lo->ldo_tls_ctx;
00609               if ( lo->ldo_tls_ctx ) {
00610                      tls_ctx_ref( lo->ldo_tls_ctx );
00611               }
00612               break;
00613        case LDAP_OPT_X_TLS_CACERTFILE:
00614               *(char **)arg = lo->ldo_tls_cacertfile ?
00615                      LDAP_STRDUP( lo->ldo_tls_cacertfile ) : NULL;
00616               break;
00617        case LDAP_OPT_X_TLS_CACERTDIR:
00618               *(char **)arg = lo->ldo_tls_cacertdir ?
00619                      LDAP_STRDUP( lo->ldo_tls_cacertdir ) : NULL;
00620               break;
00621        case LDAP_OPT_X_TLS_CERTFILE:
00622               *(char **)arg = lo->ldo_tls_certfile ?
00623                      LDAP_STRDUP( lo->ldo_tls_certfile ) : NULL;
00624               break;
00625        case LDAP_OPT_X_TLS_KEYFILE:
00626               *(char **)arg = lo->ldo_tls_keyfile ?
00627                      LDAP_STRDUP( lo->ldo_tls_keyfile ) : NULL;
00628               break;
00629        case LDAP_OPT_X_TLS_DHFILE:
00630               *(char **)arg = lo->ldo_tls_dhfile ?
00631                      LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
00632               break;
00633        case LDAP_OPT_X_TLS_CRLFILE:       /* GnuTLS only */
00634               *(char **)arg = lo->ldo_tls_crlfile ?
00635                      LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
00636               break;
00637        case LDAP_OPT_X_TLS_REQUIRE_CERT:
00638               *(int *)arg = lo->ldo_tls_require_cert;
00639               break;
00640 #ifdef HAVE_OPENSSL_CRL
00641        case LDAP_OPT_X_TLS_CRLCHECK:      /* OpenSSL only */
00642               *(int *)arg = lo->ldo_tls_crlcheck;
00643               break;
00644 #endif
00645        case LDAP_OPT_X_TLS_CIPHER_SUITE:
00646               *(char **)arg = lo->ldo_tls_ciphersuite ?
00647                      LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL;
00648               break;
00649        case LDAP_OPT_X_TLS_PROTOCOL_MIN:
00650               *(int *)arg = lo->ldo_tls_protocol_min;
00651               break;
00652        case LDAP_OPT_X_TLS_RANDOM_FILE:
00653               *(char **)arg = lo->ldo_tls_randfile ?
00654                      LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL;
00655               break;
00656        case LDAP_OPT_X_TLS_SSL_CTX: {
00657               void *retval = 0;
00658               if ( ld != NULL ) {
00659                      LDAPConn *conn = ld->ld_defconn;
00660                      if ( conn != NULL ) {
00661                             Sockbuf *sb = conn->lconn_sb;
00662                             retval = ldap_pvt_tls_sb_ctx( sb );
00663                      }
00664               }
00665               *(void **)arg = retval;
00666               break;
00667        }
00668        case LDAP_OPT_X_TLS_CONNECT_CB:
00669               *(LDAP_TLS_CONNECT_CB **)arg = lo->ldo_tls_connect_cb;
00670               break;
00671        case LDAP_OPT_X_TLS_CONNECT_ARG:
00672               *(void **)arg = lo->ldo_tls_connect_arg;
00673               break;
00674        default:
00675               return -1;
00676        }
00677        return 0;
00678 }
00679 
00680 int
00681 ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
00682 {
00683        struct ldapoptions *lo;
00684 
00685        if( ld != NULL ) {
00686               assert( LDAP_VALID( ld ) );
00687 
00688               if( !LDAP_VALID( ld ) ) {
00689                      return LDAP_OPT_ERROR;
00690               }
00691 
00692               lo = &ld->ld_options;
00693 
00694        } else {
00695               /* Get pointer to global option structure */
00696               lo = LDAP_INT_GLOBAL_OPT();   
00697               if ( lo == NULL ) {
00698                      return LDAP_NO_MEMORY;
00699               }
00700        }
00701 
00702        switch( option ) {
00703        case LDAP_OPT_X_TLS:
00704               if ( !arg ) return -1;
00705 
00706               switch( *(int *) arg ) {
00707               case LDAP_OPT_X_TLS_NEVER:
00708               case LDAP_OPT_X_TLS_DEMAND:
00709               case LDAP_OPT_X_TLS_ALLOW:
00710               case LDAP_OPT_X_TLS_TRY:
00711               case LDAP_OPT_X_TLS_HARD:
00712                      if (lo != NULL) {
00713                             lo->ldo_tls_mode = *(int *)arg;
00714                      }
00715 
00716                      return 0;
00717               }
00718               return -1;
00719 
00720        case LDAP_OPT_X_TLS_CTX:
00721               if ( lo->ldo_tls_ctx )
00722                      ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
00723               lo->ldo_tls_ctx = arg;
00724               tls_ctx_ref( lo->ldo_tls_ctx );
00725               return 0;
00726        case LDAP_OPT_X_TLS_CONNECT_CB:
00727               lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg;
00728               return 0;
00729        case LDAP_OPT_X_TLS_CONNECT_ARG:
00730               lo->ldo_tls_connect_arg = arg;
00731               return 0;
00732        case LDAP_OPT_X_TLS_CACERTFILE:
00733               if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile );
00734               lo->ldo_tls_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00735               return 0;
00736        case LDAP_OPT_X_TLS_CACERTDIR:
00737               if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir );
00738               lo->ldo_tls_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00739               return 0;
00740        case LDAP_OPT_X_TLS_CERTFILE:
00741               if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile );
00742               lo->ldo_tls_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00743               return 0;
00744        case LDAP_OPT_X_TLS_KEYFILE:
00745               if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile );
00746               lo->ldo_tls_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00747               return 0;
00748        case LDAP_OPT_X_TLS_DHFILE:
00749               if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
00750               lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00751               return 0;
00752        case LDAP_OPT_X_TLS_CRLFILE:       /* GnuTLS only */
00753               if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
00754               lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00755               return 0;
00756        case LDAP_OPT_X_TLS_REQUIRE_CERT:
00757               if ( !arg ) return -1;
00758               switch( *(int *) arg ) {
00759               case LDAP_OPT_X_TLS_NEVER:
00760               case LDAP_OPT_X_TLS_DEMAND:
00761               case LDAP_OPT_X_TLS_ALLOW:
00762               case LDAP_OPT_X_TLS_TRY:
00763               case LDAP_OPT_X_TLS_HARD:
00764                      lo->ldo_tls_require_cert = * (int *) arg;
00765                      return 0;
00766               }
00767               return -1;
00768 #ifdef HAVE_OPENSSL_CRL
00769        case LDAP_OPT_X_TLS_CRLCHECK:      /* OpenSSL only */
00770               if ( !arg ) return -1;
00771               switch( *(int *) arg ) {
00772               case LDAP_OPT_X_TLS_CRL_NONE:
00773               case LDAP_OPT_X_TLS_CRL_PEER:
00774               case LDAP_OPT_X_TLS_CRL_ALL:
00775                      lo->ldo_tls_crlcheck = * (int *) arg;
00776                      return 0;
00777               }
00778               return -1;
00779 #endif
00780        case LDAP_OPT_X_TLS_CIPHER_SUITE:
00781               if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite );
00782               lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00783               return 0;
00784 
00785        case LDAP_OPT_X_TLS_PROTOCOL_MIN:
00786               if ( !arg ) return -1;
00787               lo->ldo_tls_protocol_min = *(int *)arg;
00788               return 0;
00789        case LDAP_OPT_X_TLS_RANDOM_FILE:
00790               if ( ld != NULL )
00791                      return -1;
00792               if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile );
00793               lo->ldo_tls_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
00794               break;
00795        case LDAP_OPT_X_TLS_NEWCTX:
00796               if ( !arg ) return -1;
00797               if ( lo->ldo_tls_ctx )
00798                      ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
00799               lo->ldo_tls_ctx = NULL;
00800               return ldap_int_tls_init_ctx( lo, *(int *)arg );
00801        default:
00802               return -1;
00803        }
00804        return 0;
00805 }
00806 
00807 int
00808 ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
00809 {
00810        Sockbuf *sb;
00811        char *host;
00812        void *ssl;
00813 
00814        if ( !conn )
00815               return LDAP_PARAM_ERROR;
00816 
00817        sb = conn->lconn_sb;
00818        if( srv ) {
00819               host = srv->lud_host;
00820        } else {
00821               host = conn->lconn_server->lud_host;
00822        }
00823 
00824        /* avoid NULL host */
00825        if( host == NULL ) {
00826               host = "localhost";
00827        }
00828 
00829        (void) tls_init( tls_imp );
00830 
00831        /*
00832         * Fortunately, the lib uses blocking io...
00833         */
00834        if ( ldap_int_tls_connect( ld, conn ) < 0 ) {
00835               ld->ld_errno = LDAP_CONNECT_ERROR;
00836               return (ld->ld_errno);
00837        }
00838 
00839        ssl = ldap_pvt_tls_sb_ctx( sb );
00840        assert( ssl != NULL );
00841 
00842        /* 
00843         * compare host with name(s) in certificate
00844         */
00845        if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER &&
00846            ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) {
00847               ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host );
00848               if (ld->ld_errno != LDAP_SUCCESS) {
00849                      return ld->ld_errno;
00850               }
00851        }
00852 
00853        return LDAP_SUCCESS;
00854 }
00855 
00856 void *
00857 ldap_pvt_tls_sb_ctx( Sockbuf *sb )
00858 {
00859        void                 *p = NULL;
00860        
00861        ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p );
00862        return p;
00863 }
00864 
00865 int
00866 ldap_pvt_tls_get_strength( void *s )
00867 {
00868        tls_session *session = s;
00869 
00870        return tls_imp->ti_session_strength( session );
00871 }
00872 
00873 int
00874 ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags )
00875 {
00876        tls_session *session = s;
00877        struct berval der_dn;
00878        int rc;
00879 
00880        rc = tls_imp->ti_session_my_dn( session, &der_dn );
00881        if ( rc == LDAP_SUCCESS )
00882               rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags );
00883        return rc;
00884 }
00885 #endif /* HAVE_TLS */
00886 
00887 int
00888 ldap_start_tls( LDAP *ld,
00889        LDAPControl **serverctrls,
00890        LDAPControl **clientctrls,
00891        int *msgidp )
00892 {
00893        return ldap_extended_operation( ld, LDAP_EXOP_START_TLS,
00894               NULL, serverctrls, clientctrls, msgidp );
00895 }
00896 
00897 int
00898 ldap_install_tls( LDAP *ld )
00899 {
00900 #ifndef HAVE_TLS
00901        return LDAP_NOT_SUPPORTED;
00902 #else
00903        if ( ldap_tls_inplace( ld ) ) {
00904               return LDAP_LOCAL_ERROR;
00905        }
00906 
00907        return ldap_int_tls_start( ld, ld->ld_defconn, NULL );
00908 #endif
00909 }
00910 
00911 int
00912 ldap_start_tls_s ( LDAP *ld,
00913        LDAPControl **serverctrls,
00914        LDAPControl **clientctrls )
00915 {
00916 #ifndef HAVE_TLS
00917        return LDAP_NOT_SUPPORTED;
00918 #else
00919        int rc;
00920        char *rspoid = NULL;
00921        struct berval *rspdata = NULL;
00922 
00923        /* XXYYZ: this initiates operation only on default connection! */
00924 
00925        if ( ldap_tls_inplace( ld ) ) {
00926               return LDAP_LOCAL_ERROR;
00927        }
00928 
00929        rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS,
00930               NULL, serverctrls, clientctrls, &rspoid, &rspdata );
00931 
00932        if ( rspoid != NULL ) {
00933               LDAP_FREE(rspoid);
00934        }
00935 
00936        if ( rspdata != NULL ) {
00937               ber_bvfree( rspdata );
00938        }
00939 
00940        if ( rc == LDAP_SUCCESS ) {
00941               rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL );
00942        }
00943 
00944        return rc;
00945 #endif
00946 }
00947 
00948 /* These tags probably all belong in lber.h, but they're
00949  * not normally encountered when processing LDAP, so maybe
00950  * they belong somewhere else instead.
00951  */
00952 
00953 #define LBER_TAG_OID        ((ber_tag_t) 0x06UL)
00954 
00955 /* Tags for string types used in a DirectoryString.
00956  *
00957  * Note that IA5string is not one of the defined choices for
00958  * DirectoryString in X.520, but it gets used for email AVAs.
00959  */
00960 #define       LBER_TAG_UTF8        ((ber_tag_t) 0x0cUL)
00961 #define       LBER_TAG_PRINTABLE   ((ber_tag_t) 0x13UL)
00962 #define       LBER_TAG_TELETEX     ((ber_tag_t) 0x14UL)
00963 #define       LBER_TAG_IA5         ((ber_tag_t) 0x16UL)
00964 #define       LBER_TAG_UNIVERSAL   ((ber_tag_t) 0x1cUL)
00965 #define       LBER_TAG_BMP         ((ber_tag_t) 0x1eUL)
00966 
00967 static oid_name *
00968 find_oid( struct berval *oid )
00969 {
00970        int i;
00971 
00972        for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) {
00973               if ( oids[i].oid.bv_len != oid->bv_len ) continue;
00974               if ( !strcmp( oids[i].oid.bv_val, oid->bv_val ))
00975                      return &oids[i];
00976        }
00977        return NULL;
00978 }
00979 
00980 /* Converts BER Bitstring value to LDAP BitString value (RFC4517)
00981  *
00982  * berValue    : IN
00983  * rfc4517Value: OUT
00984  *
00985  * berValue and ldapValue should not be NULL
00986  */
00987 
00988 #define BITS_PER_BYTE       8
00989 #define SQUOTE_LENGTH       1
00990 #define B_CHAR_LENGTH       1
00991 #define STR_OVERHEAD    (2*SQUOTE_LENGTH + B_CHAR_LENGTH)
00992 
00993 static int
00994 der_to_ldap_BitString (struct berval *berValue,
00995                                    struct berval *ldapValue)
00996 {
00997        ber_len_t bitPadding=0;
00998        ber_len_t bits, maxBits;
00999        char *tmpStr;
01000        unsigned char byte;
01001        ber_len_t bitLength;
01002        ber_len_t valLen;
01003        unsigned char* valPtr;
01004 
01005        ldapValue->bv_len=0;
01006        ldapValue->bv_val=NULL;
01007 
01008        /* Gets padding and points to binary data */
01009        valLen=berValue->bv_len;
01010        valPtr=(unsigned char*)berValue->bv_val;
01011        if (valLen) {
01012               bitPadding=(ber_len_t)(valPtr[0]);
01013               valLen--;
01014               valPtr++;
01015        }
01016        /* If Block is non DER encoding fixes to DER encoding */
01017        if (bitPadding >= BITS_PER_BYTE) {
01018               if (valLen*BITS_PER_BYTE > bitPadding ) {
01019                      valLen-=(bitPadding/BITS_PER_BYTE);
01020                      bitPadding%=BITS_PER_BYTE;
01021               } else {
01022                      valLen=0;
01023                      bitPadding=0;
01024               }
01025        }
01026        /* Just in case bad encoding */
01027        if (valLen*BITS_PER_BYTE < bitPadding ) {
01028               bitPadding=0;
01029               valLen=0;
01030        }
01031 
01032        /* Gets buffer to hold RFC4517 Bit String format */
01033        bitLength=valLen*BITS_PER_BYTE-bitPadding;
01034        tmpStr=LDAP_MALLOC(bitLength + STR_OVERHEAD + 1);
01035 
01036        if (!tmpStr)
01037               return LDAP_NO_MEMORY;
01038 
01039        ldapValue->bv_val=tmpStr;
01040        ldapValue->bv_len=bitLength + STR_OVERHEAD;
01041 
01042        /* Formatting in '*binary-digit'B format */
01043        maxBits=BITS_PER_BYTE;
01044        *tmpStr++ ='\'';
01045        while(valLen) {
01046               byte=*valPtr;
01047               if (valLen==1)
01048                      maxBits-=bitPadding;
01049               for (bits=0; bits<maxBits; bits++) {
01050                      if (0x80 & byte)
01051                             *tmpStr='1';
01052                      else
01053                             *tmpStr='0';
01054                      tmpStr++;
01055                      byte<<=1;
01056               }
01057               valPtr++;
01058               valLen--;
01059        }
01060        *tmpStr++ ='\'';
01061        *tmpStr++ ='B';
01062        *tmpStr=0;
01063 
01064        return LDAP_SUCCESS;
01065 }
01066 
01067 /* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
01068  * x509_name must be raw DER. If func is non-NULL, the
01069  * constructed DN will use numeric OIDs to identify attributeTypes,
01070  * and the func() will be invoked to rewrite the DN with the given
01071  * flags.
01072  *
01073  * Otherwise the DN will use shortNames from a hardcoded table.
01074  */
01075 int
01076 ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
01077        unsigned flags )
01078 {
01079        LDAPDN newDN;
01080        LDAPRDN       newRDN;
01081        LDAPAVA *newAVA, *baseAVA;
01082        BerElementBuffer berbuf;
01083        BerElement *ber = (BerElement *)&berbuf;
01084        char oids[8192], *oidptr = oids, *oidbuf = NULL;
01085        void *ptrs[2048];
01086        char *dn_end, *rdn_end;
01087        int i, navas, nrdns, rc = LDAP_SUCCESS;
01088        size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
01089        int csize;
01090        ber_tag_t tag;
01091        ber_len_t len;
01092        oid_name *oidname;
01093 
01094        struct berval Oid, Val, oid2, *in = x509_name;
01095 
01096        assert( bv != NULL );
01097 
01098        bv->bv_len = 0;
01099        bv->bv_val = NULL;
01100 
01101        navas = 0;
01102        nrdns = 0;
01103 
01104        /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs.
01105         * An AVA is a SEQUENCE of attr and value.
01106         * Count the number of AVAs and RDNs
01107         */
01108        ber_init2( ber, in, LBER_USE_DER );
01109        tag = ber_peek_tag( ber, &len );
01110        if ( tag != LBER_SEQUENCE )
01111               return LDAP_DECODING_ERROR;
01112 
01113        for ( tag = ber_first_element( ber, &len, &dn_end );
01114               tag == LBER_SET;
01115               tag = ber_next_element( ber, &len, dn_end )) {
01116               nrdns++;
01117               for ( tag = ber_first_element( ber, &len, &rdn_end );
01118                      tag == LBER_SEQUENCE;
01119                      tag = ber_next_element( ber, &len, rdn_end )) {
01120                      tag = ber_skip_tag( ber, &len );
01121                      ber_skip_data( ber, len );
01122                      navas++;
01123               }
01124        }
01125 
01126        /* Allocate the DN/RDN/AVA stuff as a single block */    
01127        dnsize = sizeof(LDAPRDN) * (nrdns+1);
01128        dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
01129        dnsize += sizeof(LDAPAVA) * navas;
01130        if (dnsize > sizeof(ptrs)) {
01131               newDN = (LDAPDN)LDAP_MALLOC( dnsize );
01132               if ( newDN == NULL )
01133                      return LDAP_NO_MEMORY;
01134        } else {
01135               newDN = (LDAPDN)(char *)ptrs;
01136        }
01137        
01138        newDN[nrdns] = NULL;
01139        newRDN = (LDAPRDN)(newDN + nrdns+1);
01140        newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
01141        baseAVA = newAVA;
01142 
01143        /* Rewind and start extracting */
01144        ber_rewind( ber );
01145 
01146        tag = ber_first_element( ber, &len, &dn_end );
01147        for ( i = nrdns - 1; i >= 0; i-- ) {
01148               newDN[i] = newRDN;
01149 
01150               for ( tag = ber_first_element( ber, &len, &rdn_end );
01151                      tag == LBER_SEQUENCE;
01152                      tag = ber_next_element( ber, &len, rdn_end )) {
01153 
01154                      *newRDN++ = newAVA;
01155                      tag = ber_skip_tag( ber, &len );
01156                      tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM );
01157                      if ( tag != LBER_TAG_OID ) {
01158                             rc = LDAP_DECODING_ERROR;
01159                             goto nomem;
01160                      }
01161 
01162                      oid2.bv_val = oidptr;
01163                      oid2.bv_len = oidrem;
01164                      if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) {
01165                             rc = LDAP_DECODING_ERROR;
01166                             goto nomem;
01167                      }
01168                      oidname = find_oid( &oid2 );
01169                      if ( !oidname ) {
01170                             newAVA->la_attr = oid2;
01171                             oidptr += oid2.bv_len + 1;
01172                             oidrem -= oid2.bv_len + 1;
01173 
01174                             /* Running out of OID buffer space? */
01175                             if (oidrem < 128) {
01176                                    if ( oidsize == 0 ) {
01177                                           oidsize = sizeof(oids) * 2;
01178                                           oidrem = oidsize;
01179                                           oidbuf = LDAP_MALLOC( oidsize );
01180                                           if ( oidbuf == NULL ) goto nomem;
01181                                           oidptr = oidbuf;
01182                                    } else {
01183                                           char *old = oidbuf;
01184                                           oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
01185                                           if ( oidbuf == NULL ) goto nomem;
01186                                           /* Buffer moved! Fix AVA pointers */
01187                                           if ( old != oidbuf ) {
01188                                                  LDAPAVA *a;
01189                                                  long dif = oidbuf - old;
01190 
01191                                                  for (a=baseAVA; a<=newAVA; a++){
01192                                                         if (a->la_attr.bv_val >= old &&
01193                                                                a->la_attr.bv_val <= (old + oidsize))
01194                                                                a->la_attr.bv_val += dif;
01195                                                  }
01196                                           }
01197                                           oidptr = oidbuf + oidsize - oidrem;
01198                                           oidrem += oidsize;
01199                                           oidsize *= 2;
01200                                    }
01201                             }
01202                      } else {
01203                             if ( func ) {
01204                                    newAVA->la_attr = oidname->oid;
01205                             } else {
01206                                    newAVA->la_attr = oidname->name;
01207                             }
01208                      }
01209                      newAVA->la_private = NULL;
01210                      newAVA->la_flags = LDAP_AVA_STRING;
01211                      tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM );
01212                      switch(tag) {
01213                      case LBER_TAG_UNIVERSAL:
01214                             /* This uses 32-bit ISO 10646-1 */
01215                             csize = 4; goto to_utf8;
01216                      case LBER_TAG_BMP:
01217                             /* This uses 16-bit ISO 10646-1 */
01218                             csize = 2; goto to_utf8;
01219                      case LBER_TAG_TELETEX:
01220                             /* This uses 8-bit, assume ISO 8859-1 */
01221                             csize = 1;
01222 to_utf8:             rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
01223                             newAVA->la_flags |= LDAP_AVA_NONPRINTABLE;
01224 allocd:
01225                             newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
01226                             if (rc != LDAP_SUCCESS) goto nomem;
01227                             break;
01228                      case LBER_TAG_UTF8:
01229                             newAVA->la_flags |= LDAP_AVA_NONPRINTABLE;
01230                             /* This is already in UTF-8 encoding */
01231                      case LBER_TAG_IA5:
01232                      case LBER_TAG_PRINTABLE:
01233                             /* These are always 7-bit strings */
01234                             newAVA->la_value = Val;
01235                             break;
01236                      case LBER_BITSTRING:
01237                             /* X.690 bitString value converted to RFC4517 Bit String */
01238                             rc = der_to_ldap_BitString( &Val, &newAVA->la_value );
01239                             goto allocd;
01240                      default:
01241                             /* Not a string type at all */
01242                             newAVA->la_flags = 0;
01243                             newAVA->la_value = Val;
01244                             break;
01245                      }
01246                      newAVA++;
01247               }
01248               *newRDN++ = NULL;
01249               tag = ber_next_element( ber, &len, dn_end );
01250        }
01251               
01252        if ( func ) {
01253               rc = func( newDN, flags, NULL );
01254               if ( rc != LDAP_SUCCESS )
01255                      goto nomem;
01256        }
01257 
01258        rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
01259 
01260 nomem:
01261        for (;baseAVA < newAVA; baseAVA++) {
01262               if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
01263                      LDAP_FREE( baseAVA->la_attr.bv_val );
01264               if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
01265                      LDAP_FREE( baseAVA->la_value.bv_val );
01266        }
01267 
01268        if ( oidsize != 0 )
01269               LDAP_FREE( oidbuf );
01270        if ( newDN != (LDAPDN)(char *) ptrs )
01271               LDAP_FREE( newDN );
01272        return rc;
01273 }
01274