X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Frequest.c;h=6098f0c904b14c48389c189c55252c6f0ff78dc2;hb=e22dc83ac096d1239a6903199f5dc3231b0f444b;hp=9894301b88dcf52090aa89464db300a2abc41b03;hpb=d4124e0e031f5b76a80f9c25a04146d334bcf898;p=openldap diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index 9894301b88..6098f0c904 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2008 The OpenLDAP Foundation. + * Copyright 1998-2009 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -352,6 +352,32 @@ ldap_send_server_request( return( msgid ); } +/* return 0 if no StartTLS ext, 1 if present, 2 if critical */ +static int +find_tls_ext( LDAPURLDesc *srv ) +{ + int i, crit; + char *ext; + + if ( !srv->lud_exts ) + return 0; + + for (i=0; srv->lud_exts[i]; i++) { + crit = 0; + ext = srv->lud_exts[i]; + if ( ext[0] == '!') { + ext++; + crit = 1; + } + if ( !strcasecmp( ext, "StartTLS" ) || + !strcasecmp( ext, "X-StartTLS" ) || + !strcmp( ext, LDAP_EXOP_START_TLS )) { + return crit + 1; + } + } + return 0; +} + LDAPConn * ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind ) @@ -426,6 +452,38 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); #endif + if ( connect ) { +#ifdef HAVE_TLS + if ( lc->lconn_server->lud_exts ) { + int rc, ext = find_tls_ext( lc->lconn_server ); + if ( ext ) { + LDAPConn *savedefconn; + + savedefconn = ld->ld_defconn; + ++lc->lconn_refcnt; /* avoid premature free */ + ld->ld_defconn = lc; + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); + ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); +#endif + rc = ldap_start_tls_s( ld, NULL, NULL ); +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); + ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); +#endif + ld->ld_defconn = savedefconn; + --lc->lconn_refcnt; + + if ( rc != LDAP_SUCCESS && ext == 2 ) { + ldap_free_connection( ld, lc, 1, 0 ); + return NULL; + } + } + } +#endif + } + if ( bind != NULL ) { int err = 0; LDAPConn *savedefconn; @@ -577,8 +635,7 @@ find_connection( LDAP *ld, LDAPURLDesc *srv, int any ) if ( lsu_port == lcu_port && strcmp( lcu->lud_scheme, lsu->lud_scheme ) == 0 - && lcu->lud_host != NULL && *lcu->lud_host != '\0' - && lsu->lud_host != NULL && *lsu->lud_host != '\0' + && lcu->lud_host != NULL && lsu->lud_host != NULL && strcasecmp( lsu->lud_host, lcu->lud_host ) == 0 ) { found = 1; @@ -631,6 +688,9 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) } else { prevlc->lconn_next = tmplc->lconn_next; } + if ( ld->ld_defconn == lc ) { + ld->ld_defconn = NULL; + } break; } prevlc = tmplc; @@ -639,6 +699,28 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex ); #endif + /* process connection callbacks */ + { + struct ldapoptions *lo; + ldaplist *ll; + ldap_conncb *cb; + + lo = &ld->ld_options; + if ( lo->ldo_conn_cbs ) { + for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { + cb = ll->ll_data; + cb->lc_del( ld, lc->lconn_sb, cb ); + } + } + lo = LDAP_INT_GLOBAL_OPT(); + if ( lo->ldo_conn_cbs ) { + for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { + cb = ll->ll_data; + cb->lc_del( ld, lc->lconn_sb, cb ); + } + } + } + if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { ldap_mark_select_clear( ld, lc->lconn_sb ); if ( unbind ) { @@ -652,6 +734,9 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) } ldap_int_sasl_close( ld, lc ); +#ifdef HAVE_GSSAPI + ldap_int_gssapi_close( ld, lc ); +#endif ldap_free_urllist( lc->lconn_server ); @@ -675,6 +760,8 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) if ( lc->lconn_sb != ld->ld_sb ) { ber_sockbuf_free( lc->lconn_sb ); + } else { + ber_int_sb_close( lc->lconn_sb ); } if ( lc->lconn_rebind_queue != NULL) { @@ -991,10 +1078,18 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char * } if( srv->lud_crit_exts ) { - /* we do not support any extensions */ - ld->ld_errno = LDAP_NOT_SUPPORTED; - rc = -1; - goto done; + int ok = 0; +#ifdef HAVE_TLS + /* If StartTLS is the only critical ext, OK. */ + if ( find_tls_ext( srv ) == 2 && srv->lud_crit_exts == 1 ) + ok = 1; +#endif + if ( !ok ) { + /* we do not support any other extensions */ + ld->ld_errno = LDAP_NOT_SUPPORTED; + rc = -1; + goto done; + } } /* check connection for re-bind in progress */ @@ -1002,7 +1097,7 @@ ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char * /* See if we've already requested this DN with this conn */ LDAPRequest *lp; int looped = 0; - int len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; + ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; for ( lp = origreq; lp; ) { if ( lp->lr_conn == lc && len == lp->lr_dn.bv_len @@ -1261,7 +1356,7 @@ ldap_chase_referrals( LDAP *ld, if (( lc = find_connection( ld, srv, 1 )) != NULL ) { LDAPRequest *lp; int looped = 0; - int len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; + ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; for ( lp = lr; lp; lp = lp->lr_parent ) { if ( lp->lr_conn == lc && len == lp->lr_dn.bv_len )