diff options
Diffstat (limited to 'usr/src/lib/libldap4/common/result.c')
-rw-r--r-- | usr/src/lib/libldap4/common/result.c | 1657 |
1 files changed, 0 insertions, 1657 deletions
diff --git a/usr/src/lib/libldap4/common/result.c b/usr/src/lib/libldap4/common/result.c deleted file mode 100644 index 07b21483c6..0000000000 --- a/usr/src/lib/libldap4/common/result.c +++ /dev/null @@ -1,1657 +0,0 @@ -/* - * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Copyright (c) 1990 Regents of the University of Michigan. - * All rights reserved. - * - * result.c - wait for an ldap result - */ - -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif - -#include <stdio.h> -#include <string.h> -#ifdef MACOS -#include <stdlib.h> -#include <time.h> -#include "macos.h" -#else /* MACOS */ -#if defined( DOS ) || defined( _WIN32 ) -#include <time.h> -#include "msdos.h" -#ifdef PCNFS -#include <tklib.h> -#include <tk_errno.h> -#include <bios.h> -#endif /* PCNFS */ -#ifdef NCSA -#include "externs.h" -#endif /* NCSA */ -#else /* DOS */ -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <errno.h> -#ifdef _AIX -#include <sys/select.h> -#endif /* _AIX */ -#include "portable.h" -#endif /* DOS */ -#endif /* MACOS */ -#ifdef VMS -#include "ucx_select.h" -#endif -#include "lber.h" -#include "ldap.h" -#include "ldap-private.h" -#include "ldap-int.h" - -#ifdef USE_SYSCONF -#include <unistd.h> -#endif /* USE_SYSCONF */ - -#ifdef NEEDPROTOS -static int ldap_abandoned( LDAP *ld, int msgid ); -static int ldap_mark_abandoned( LDAP *ld, int msgid ); -static int wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, - LDAPMessage **result ); -static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc, - LDAPMessage **result ); -static int build_result_ber( LDAP *ld, BerElement *ber, LDAPRequest *lr ); -static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ); -#ifdef CLDAP -static int ldap_select1( LDAP *ld, struct timeval *timeout ); -#endif -static int Ref_AddToRequest(LDAPRequest *lr, char **refs); -static void Ref_FreeAll(LDAPRequest *lr); -#else /* NEEDPROTOS */ -static int ldap_abandoned(); -static int ldap_mark_abandoned(); -static int wait4msg(); -static int read1msg(); -static int build_result_ber(); -static void merge_error_info(); -#ifdef CLDAP -static int ldap_select1(); -#endif -#endif /* NEEDPROTOS */ - -#if !defined( MACOS ) && !defined( DOS ) -extern int errno; -#endif - -/* - * ldap_result - wait for an ldap result response to a message from the - * ldap server. If msgid is -1, any message will be accepted, otherwise - * ldap_result will wait for a response with msgid. - * If all is LDAP_MSG_ONE the first message with id msgid will be accepted. - * If all is LDAP_MSG_RECEIVED, the received messages with the id msgid will - * be accepted. - * Otherwise, ldap_result will wait for all responses with id msgid and - * then return a pointer to the entire list of messages. This is only - * useful for search responses, which can be of 3 message types (zero or - * more entries, zero or more references, one or more results). The type - * of the first message* received is returned. - * When waiting, any messages that have been abandoned are discarded. - * - * Example: - * ldap_result( s, msgid, all, timeout, result ) - */ -int -ldap_result( LDAP *ld, int msgid, int all, struct timeval *timeout, - LDAPMessage **result ) -{ - LDAPMessage *lm, *lastlm, *nextlm; - int rv; - - /* - * First, look through the list of responses we have received on - * this association and see if the response we're interested in - * is there. If it is, return it. If not, call wait4msg() to - * wait until it arrives or timeout occurs. - */ - -#ifdef _REENTRANT - LOCK_RESPONSE(ld); - LOCK_LDAP(ld); -#endif - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 223, "ldap_result\n"), 0, 0, 0 ); - - *result = NULLMSG; - lastlm = NULLMSG; - - /* look in the received responses */ - for ( lm = ld->ld_responses; lm != NULLMSG; lm = nextlm ) { - nextlm = lm->lm_next; - - /* if the msg has been abandonned, free it */ - if ( ldap_abandoned( ld, lm->lm_msgid ) ) { - ldap_mark_abandoned( ld, lm->lm_msgid ); - - if ( lastlm == NULLMSG ) { - ld->ld_responses = lm->lm_next; - } else { - lastlm->lm_next = nextlm; - } - - ldap_msgfree( lm ); - - continue; - } - - if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) { - LDAPMessage *tmp; - - /* If return ONE or RECEIVED message(s) or not a search result, return lm */ - if ( all == LDAP_MSG_ONE || all == LDAP_MSG_RECEIVED - || (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT - && lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY - && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) ) - break; - - /* Search in the set of messages if one is a search result */ - for ( tmp = lm; tmp != NULLMSG; tmp = tmp->lm_chain ) { - if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT ) - break; - } - /* No, well wait for the result message */ - if ( tmp == NULLMSG ) { -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - rv = wait4msg( ld, msgid, all, timeout, result ); -#ifdef _REENTRANT - UNLOCK_RESPONSE(ld); -#endif - return( rv ); - } - /* Here we have the Search result pointed by tmp */ - break; - } - /* Check next response */ - lastlm = lm; - } - - /* No response matching found : Wait for one */ - if ( lm == NULLMSG ) { -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - rv = wait4msg( ld, msgid, all, timeout, result ); -#ifdef _REENTRANT - UNLOCK_RESPONSE(ld); -#endif - return( rv ); - } - - /* lm points to the message (chain) to return */ - - /* Remove message to return from ld_responses list */ - if ( lastlm == NULLMSG ) { - if (all == LDAP_MSG_ONE && lm->lm_chain != NULLMSG){ - ld->ld_responses = lm->lm_chain; - } else { - ld->ld_responses = lm->lm_next; - } - } else { - if (all == LDAP_MSG_ONE && lm->lm_chain != NULLMSG) { - lastlm->lm_next = lm->lm_chain; - } else { - lastlm->lm_next = lm->lm_next; - } - } - - if ( all == LDAP_MSG_ONE ) - lm->lm_chain = NULLMSG; - /* Otherwise return the whole chain */ - /* No reponses attached */ - lm->lm_next = NULLMSG; - - *result = lm; - ld->ld_errno = LDAP_SUCCESS; - rv = lm->lm_msgtype; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); - UNLOCK_RESPONSE(ld); -#endif - return( rv ); -} - -static int -wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, - LDAPMessage **result ) -{ - int rc; - struct timeval tv, *tvp; - time_t start_time, tmp_time; - LDAPConn *lc, *nextlc; - -#ifdef LDAP_DEBUG - if ( timeout == NULL ) { - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 224, "wait4msg (infinite timeout)\n"), - 0, 0, 0 ); - } else { - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 225, "wait4msg (timeout %1$ld sec, %2$ld usec)\n"), - timeout->tv_sec, timeout->tv_usec, 0 ); - } -#endif /* LDAP_DEBUG */ - - if ( timeout == NULL ) { - tvp = NULL; - } else { - tv = *timeout; - tvp = &tv; - start_time = time( NULL ); - } - - rc = -2; - while ( rc == -2 ) { -#ifdef LDAP_DEBUG - if ( ldap_debug & LDAP_DEBUG_TRACE ) { - dump_connection( ld, ld->ld_conns, 1 ); - dump_requests_and_responses( ld ); - } -#endif /* LDAP_DEBUG */ - for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { - if ( lc->lconn_sb->sb_ber.ber_ptr < - lc->lconn_sb->sb_ber.ber_end ) { - /* A Message is available, decode and process it */ - rc = read1msg( ld, msgid, all, lc->lconn_sb, - lc, result ); - break; - } - } - /* There was no message available : Wait for one */ - if ( lc == NULL ) { - rc = do_ldap_select( ld, tvp ); - - -#if defined( LDAP_DEBUG ) && !defined( MACOS ) && !defined( DOS ) - if ( rc == -1 ) { - Debug( LDAP_DEBUG_TRACE, - catgets(slapdcat, 1, 226, "do_ldap_select returned -1: errno %d\n"), - errno, 0, 0 ); - } -#endif - -#if !defined( MACOS ) && !defined( DOS ) - if ( rc == 0 || ( rc == -1 && (ld->ld_restart || errno != EINTR ))) { -#else - if ( rc == -1 || rc == 0 ) { -#endif - ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : - LDAP_TIMEOUT); - if ( rc == -1 ) { -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - nsldapi_connection_lost_nolock( ld, NULL); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - } - return( rc ); - } - - if ( rc == -1 ) { - rc = -2; /* select interrupted: Continue the loop */ - } else { - rc = -2; - for ( lc = ld->ld_conns; rc == -2 && lc != NULL; - lc = nextlc ) { - nextlc = lc->lconn_next; - if ( lc->lconn_status == LDAP_CONNST_CONNECTED) { - /* Check on each connection. */ - long is_ready = is_read_ready( ld, lc->lconn_sb ); - - if (is_ready > 0) { - /* A Message is available, decode and process it */ - rc = read1msg( ld, msgid, all, - lc->lconn_sb, lc, result ); - } else if ( is_ready < 0){ - /* Error in the select : what to do in here ? */ - /* So far : */ - rc = -1; - } - } - } - } - } - - if ( rc == -2 && tvp != NULL ) { - tmp_time = time( NULL ); - if (( tv.tv_sec -= ( tmp_time - start_time )) <= 0 ) { - /* At this point if all == LDAP_MSG_RECEIVED, we must - return all available messages for the msgid */ - if (all == LDAP_MSG_RECEIVED) { - /* Search in responses if some have the correct id */ - /* if yes return the chain */ - /* Otherwise return timeout */ - break; - } - - rc = 0; /* timed out */ - ld->ld_errno = LDAP_TIMEOUT; - break; - } - - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 227, "wait4msg: %ld secs to go\n"), - tv.tv_sec, 0, 0 ); - start_time = tmp_time; - } - } - - return( rc ); -} - - -static int -read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, - LDAPConn *lc, - LDAPMessage **result ) -{ - BerElement ber; - LDAPMessage *new, *L_res, *l, *prev, *tmp; - int id; - unsigned int tag, atag, len; - int foundit = 0; - LDAPRequest *lr, *lrparent; - LDAPRef *theReferences; - BerElement tmpber; - int rc, refer_cnt, hadref, simple_request, samereq = 0, total_count; - int retcode; - int theErrCode = LDAP_SUCCESS; - unsigned int lderr; - char *msgtypestr; - char ** theRefs = NULL; - char * theOid = NULL; - char *lddn, *lderrmsg; - - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 228, "read1msg\n"), 0, 0, 0 ); - -read_from_sb: - lderr = LDAP_SUCCESS; /* Be optimistic */ - - ber_zero_init( &ber, 0 ); - set_ber_options( ld, &ber ); - - /* get the next message */ - if ( (tag = ber_get_next( sb, &len, &ber )) - != LDAP_TAG_MESSAGE ) { - ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : - LDAP_LOCAL_ERROR); - if ( tag == LBER_DEFAULT ) { -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - nsldapi_connection_lost_nolock( ld, sb ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - } - return( -1 ); - } - - /* message id */ - if ( ber_get_int( &ber, &id ) == LBER_ERROR ) { - ld->ld_errno = LDAP_DECODING_ERROR; - return( -1 ); - } - - /* if it's been abandoned, toss it */ - if ( ldap_abandoned( ld, (int)id ) ) { - free( ber.ber_buf ); /* gack! */ - return( -2 ); /* continue looking */ - } - - /* the message type */ - if ( (tag = ber_peek_tag( &ber, &len )) == LBER_ERROR ) { - ld->ld_errno = LDAP_DECODING_ERROR; - return( -1 ); - } - - /* KE - * Treat unsolicited notification if we got one! - * id==0 - * tag==LDAP_RES_EXTENDED - * - * resultCode== protocolError - * strongAuthRequired - * unavailable - * tag==LDAP_TAG_EXT_RESPNAME - * response name (oid)==1.3.6.1.1.4.1.1466.20036 - * no response field - * - * Example: - * -------- - * Ber format: {iaata} - * which means: returnCode dn errorMessage LDAP_TAG_EXT_RESPNAME "1.3.6.1.1.4.1.1466.20036" - */ - if ( (id==0) && (tag==LDAP_RES_EXTENDED) ) - { - tmpber = ber; - if (ber_scanf( &ber, "{iaa", &lderr, &lddn, &lderrmsg) != LBER_ERROR) - { - if (ber_peek_tag ( &ber, &atag) == LDAP_TAG_EXT_RESPNAME) - { - if ( ber_get_stringa( &ber, &theOid) == LBER_ERROR ) - { - ld->ld_errno = LDAP_DECODING_ERROR; - return(-1); - } - } - else - { - ld->ld_errno = LDAP_DECODING_ERROR; - return(-1); - } - - if (ber_peek_tag ( &ber, &atag) == LDAP_TAG_EXT_RESPONSE) - { - /* this field must be absent */ - ld->ld_errno = LDAP_DECODING_ERROR; - return(-1); - } - if ( ber_scanf(&ber, "}")== LBER_ERROR) - { - ld->ld_errno = LDAP_DECODING_ERROR; - return(-1); - } - - /* make a new ldap message to return the result */ - if ( (new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) )) == NULL ) - { - ld->ld_errno = LDAP_NO_MEMORY; - return(-1); - } - new->lm_msgid = 0; - new->lm_msgtype = tag; - new->lm_ber = ber_dup( &tmpber ); - - if ( (strncmp(theOid, "1.3.6.1.1.4.1.1466.20036", 24)==0) && - (lderr==LDAP_PROTOCOL_ERROR) || - (lderr==LDAP_STRONG_AUTH_REQUIRED) || - (lderr==LDAP_UNAVAILABLE) ) - { - /* make a new ldap message to return the result */ - if ( (L_res = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) )) == NULL ) - { - ld->ld_errno = LDAP_NO_MEMORY; - return(-1); - } - L_res->lm_msgid = 0; - L_res->lm_msgtype = tag; - L_res->lm_ber = ber_dup( &tmpber ); - *result = L_res; - - /* It is a notice of disconnection - * Return immediatly with an error code to stop - * reading any new message and to prevent the use - */ - ld->ld_errno = LDAP_SERVER_DOWN; - ldap_insert_notif(ld, new); /* in head */ - return(-1); - } - else - { - /* This is another notification - * Keep on the processing of received messages - */ - ldap_add_notif(ld, new); /* in tail */ - goto read_from_sb; - } - } - else - { - Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1673, "Error while decoding Extended Response message"), NULL, NULL, NULL); - ld->ld_errno = LDAP_DECODING_ERROR; - return(-1); - } - } - else if (( lr = find_request_by_msgid( ld, id )) == NULL ) - { - Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 229, "no request for response with msgid %ld (tossing)\n"), id, 0, 0 ); - free( ber.ber_buf ); /* gack! */ - return( -2 ); /* continue looking */ - } - - if (tag == LDAP_RES_SEARCH_ENTRY) - msgtypestr = catgets(slapdcat, 1, 1281, "search entry"); - else if (tag == LDAP_RES_SEARCH_REFERENCE) - msgtypestr = catgets(slapdcat, 1, 1282, "search reference"); - else - msgtypestr = catgets(slapdcat, 1, 1283, "result"); - - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 230, "got %1$s msgid %2$ld, original id %3$d\n"), - msgtypestr, id, lr->lr_origid ); - - id = lr->lr_origid; - - /* REFERRALS HANDLING*/ - refer_cnt = 0; - simple_request = 0; - hadref = 0; - rc = -2; /* default is to keep looking (no response found) */ - lr->lr_res_msgtype = tag; - - if ( tag != LDAP_RES_SEARCH_ENTRY ) { /* If it's not an entry, ie it's a result or a reference */ - if ( ld->ld_version >= LDAP_VERSION2 && - ( lr->lr_parent != NULL || - ld->ld_follow_referral /* || ClientControl to follow referral present */ )) { - tmpber = ber; - if (tag == LDAP_RES_SEARCH_REFERENCE){ - /* LDAP V3 reference. Decode it */ - Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "LDAP search reference received. Will follow it later\n"), - 0, 0,0); - if (ber_scanf(&tmpber, "{v}", &theRefs) == LBER_ERROR){ - Debug ( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1284, "Error while decoding Search Reference Result message\n"), - NULL, NULL, NULL); - rc = -1; - theRefs = NULL; - } else { - /* Store the referrals in request. We will follow them when the result arrives */ - Ref_AddToRequest(lr, theRefs); - theRefs = NULL; - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; - return (rc); - } - } else { - if (ber_scanf( &tmpber, "{iaa", &lderr, &lr->lr_res_matched, &lr->lr_res_error) != LBER_ERROR){ - if (lderr == LDAP_PARTIAL_RESULTS){ - Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "LDAPv2 partial error received\n"), 0, 0,0); - /* Ldapv2 referrals */ - theRefs = ldap_errormsg2referrals(lr->lr_res_error); - ber_scanf(&tmpber, "}"); - } else if (lderr == LDAP_REFERRAL ){ - /* We have some referrals, decode them */ - Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "LDAPv3 referral error received\n"), 0, 0,0); - if (ber_peek_tag ( &tmpber, &atag) == LDAP_TAG_REFERRAL){ - if (ber_scanf(&tmpber, "{v}}", &theRefs) == LBER_ERROR){ - Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1285, "Error while decoding referrals in msg\n"), - NULL, NULL, NULL ); - rc = -1; /* ??? */ - theRefs = NULL; - } - } /* else error there should be at least one ref */ - } else if (((lderr == LDAP_NO_SUCH_OBJECT) || - (lderr == LDAP_BUSY) || - (lderr == LDAP_UNAVAILABLE) || - (lderr == LDAP_SERVER_DOWN) || - (lderr == LDAP_CONNECT_ERROR)) && - (lr->lr_parent != NULL) && /* its subrequest */ - (lr->lr_ref_tofollow != NULL)) { /* And it has some other referral to try */ - samereq = 1; - theRefs = lr->lr_ref_tofollow; - lr->lr_ref_tofollow = NULL; - lrparent = lr->lr_parent; - /* delete lr */ - free_request(ld, lr); - /* lr now points on parent request */ - lr = lrparent; - /* Follow referrals */ - } else { - /* Here we have a simple result */ - hadref = lr->lr_outrefcnt; - } - } else { - Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1286, "Error while decoding result for request %$1d\n"), - lr->lr_origid, NULL, NULL); - rc = -1; /* ??? */ - } - } - - total_count = 0; - if (tag != LDAP_RES_SEARCH_REFERENCE && lr->lr_references) { - /* Some search references pending... Let's try to chase them */ - hadref = 1; - theReferences = lr->lr_references; - - Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Now following the search references received\n"), - 0, 0,0); - - while (theReferences != NULL){ - if ((retcode = chase_referrals(ld, lr, theReferences->lref_refs , &refer_cnt, 0)) != LDAP_SUCCESS) { - /* think about what to do */ - Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, -1, "Error while chasing referral (%1$d)\n"), - retcode, NULL, NULL); - theErrCode = LDAP_REFERRAL; - } - if (refer_cnt >= 0) - total_count += refer_cnt; - theReferences = theReferences->lref_next; - } - Ref_FreeAll(lr); - if (theErrCode != LDAP_SUCCESS) { - if (ld->ld_error != NULL && *ld->ld_error) { - if (lr->lr_res_error) - free(lr->lr_res_error); - lr->lr_res_error = strdup(ld->ld_error); - } - } - lr->lr_res_errno = theErrCode; - } - /* if theRefs != NULL we have some referrals to chase, do it */ - if (theRefs){ - hadref = 1; - if ((retcode = chase_referrals(ld, lr, theRefs, &refer_cnt, samereq)) != LDAP_SUCCESS){ - /* think about what to do */ - Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, -1, "Error while chasing referral (%1$d)\n"), - retcode, NULL, NULL); - } - - if (refer_cnt >= 0) - total_count += refer_cnt; - - ldap_value_free(theRefs); - if (samereq){ /* Just tried another referral for same request */ - free(ber.ber_buf); - ber.ber_buf = NULL; - rc = -2; - /* continue */ - } - if (retcode != LDAP_SUCCESS) { - if (ld->ld_version == LDAP_VERSION2){ - if (lr->lr_res_error) - free(lr->lr_res_error); - lr->lr_res_error = ldap_referral2error_msg(lr->lr_ref_unfollowed); - } else if (ld->ld_error != NULL && *ld->ld_error) { - if (lr->lr_res_error) - free(lr->lr_res_error); - lr->lr_res_error = strdup(ld->ld_error); - } - } - lr->lr_res_errno = ld->ld_errno; - - } else if (theErrCode == LDAP_SUCCESS) { - /* no referral have been chased */ - lr->lr_res_errno = (lderr == LDAP_PARTIAL_RESULTS || lderr == LDAP_REFERRAL) ? LDAP_SUCCESS : lderr; - } - - Debug( LDAP_DEBUG_TRACE, - catgets(slapdcat, 1, 231, "new result: res_errno: %1$d, res_error: <%2$s>, res_matched: <%3$s>\n"), - lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", - lr->lr_res_matched ? lr->lr_res_matched : "" ); - } - - - Debug( LDAP_DEBUG_TRACE, - catgets(slapdcat, 1, 232, "read1msg: %1$d new referrals\n"), total_count, 0, 0 ); - - if ( refer_cnt != 0 ) { /* chasing referrals */ - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; - if ( refer_cnt < 0 ) { - return( -1 ); /* fatal error */ - } - lr->lr_status = LDAP_REQST_CHASINGREFS; - } else if (tag == LDAP_RES_SEARCH_REFERENCE && !ld->ld_follow_referral) { - /* We had a ref and we don't follow referral : Do nothing there ?! */ - Debug( LDAP_DEBUG_TRACE, - catgets(slapdcat, 1, -1, "read1msg: returning search reference\n"), 0, 0, 0 ); - - } else { - /* No referral chasing */ - if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { - /* request without any referrals */ - simple_request = ( hadref ? 0 : 1 ); - } else { - /* request with referrals or child request */ - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; - } - - - while ( lr->lr_parent != NULL ) { - merge_error_info( ld, lr->lr_parent, lr ); - lr = lr->lr_parent; - if ( --lr->lr_outrefcnt > 0 ) { - break; /* not completedly done yet */ - } - } - - if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) { /* The main request has no more outstanding refs */ - id = lr->lr_msgid; - tag = lr->lr_res_msgtype; - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 233, "request %1$ld done\n"), - id, 0, 0 ); - Debug( LDAP_DEBUG_TRACE, - catgets(slapdcat, 1, 234, "res_errno: %1$d, res_error: <%2$s>, res_matched: <%3$s>\n"), - lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", - lr->lr_res_matched ? lr->lr_res_matched : "" ); - if ( !simple_request ) { /* We have to rebuild the result */ - if ( ber.ber_buf != NULL ) { - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; - } - if ( build_result_ber( ld, &ber, lr ) - == LBER_ERROR ) { - ld->ld_errno = LDAP_NO_MEMORY; - rc = -1; /* fatal error */ - } - } - - free_request( ld, lr ); - } - - if ( lc != NULL ) { - free_connection( ld, lc, 0, 1 ); - } - } - } - - if ( ber.ber_buf == NULL ) { /* If the buffer has been freed, return */ - return( rc ); - } - /* End of REFERRALS */ - - /* make a new ldap message */ - if ( (new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) )) - == NULL ) { - ld->ld_errno = LDAP_NO_MEMORY; - return( -1 ); - } - new->lm_msgid = (int)id; - new->lm_msgtype = tag; - new->lm_ber = ber_dup( &ber ); - -#ifndef NO_CACHE - if ( ld->ld_cache != NULL ) { - add_result_to_cache( ld, new ); - } -#endif /* NO_CACHE */ - - /* is this the one we're looking for? */ - if ( msgid == LDAP_RES_ANY || id == msgid ) { - if ( all == LDAP_MSG_ONE /* all apply only to search, so if not a search,return the val */ - || (new->lm_msgtype != LDAP_RES_SEARCH_RESULT - && new->lm_msgtype != LDAP_RES_SEARCH_ENTRY - && new->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) ) { - *result = new; - ld->ld_errno = LDAP_SUCCESS; - return( tag ); - } else if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT) { - foundit = 1; /* return the chain later */ - } - } - - /* - * if not, we must add it to the list of responses. if - * the msgid is already there, it must be part of an existing - * search response. - */ - - prev = NULLMSG; - for ( l = ld->ld_responses; l != NULLMSG; l = l->lm_next ) { - if ( l->lm_msgid == new->lm_msgid ) - break; - prev = l; - } - - /* not part of an existing search response */ - if ( l == NULLMSG ) { - if ( foundit ) { /* it a search result anyway, so return it */ - *result = new; - ld->ld_errno = LDAP_SUCCESS; - return( tag ); - } - - new->lm_next = ld->ld_responses; - ld->ld_responses = new; - return( -2 ); /* continue looking */ - } - - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 235, "adding response id %1$d type %2$d:\n"), - new->lm_msgid, new->lm_msgtype, 0 ); - - /* part of a search response - add to end of list of entries or references */ - for ( tmp = l; tmp->lm_chain != NULLMSG && - (tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY || - tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE); - tmp = tmp->lm_chain ) - ; /* NULL */ - tmp->lm_chain = new; - - /* return the whole chain if that's what we were looking for */ - if ( foundit ) { - if ( prev == NULLMSG ) - ld->ld_responses = l->lm_next; - else - prev->lm_next = l->lm_next; - *result = l; - ld->ld_errno = LDAP_SUCCESS; - return( l->lm_msgtype ); /* Patch 16 : was return(tag) */ - } - - return( -2 ); /* continue looking */ -} - - -static int -build_result_ber( LDAP *ld, BerElement *ber, LDAPRequest *lr ) -{ - unsigned int len; - int along; - - Debug (LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1287, "=> building_ber_error msgid %ld\n"), lr->lr_msgid, 0,0); - ber_zero_init( ber, 0 ); - set_ber_options( ld, ber ); - if (ld->ld_version == LDAP_VERSION3){ - if ( ber_printf( ber, "{it{ess", - lr->lr_msgid, - lr->lr_res_msgtype, - lr->lr_res_errno, - lr->lr_res_matched ? lr->lr_res_matched : "", - lr->lr_res_error ? lr->lr_res_error : "" ) == LBER_ERROR){ - return (LBER_ERROR); - } - if (lr->lr_res_errno == LDAP_REFERRAL && - ber_printf(ber, "t{v}", LDAP_TAG_REFERRAL, lr->lr_ref_unfollowed) == LBER_ERROR){ - return (LBER_ERROR); - } - if (ber_printf(ber, "}}") == LBER_ERROR){ - return (LBER_ERROR); - } - } else { - if ( ber_printf( ber, "{it{ess}}", - lr->lr_msgid, - lr->lr_res_msgtype, - lr->lr_res_errno, - lr->lr_res_matched ? lr->lr_res_matched : "", - lr->lr_res_error ? lr->lr_res_error : "" ) == LBER_ERROR ) { - return( LBER_ERROR ); - } - } - - ber_reset( ber, 1 ); - if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) { - return( LBER_ERROR ); - } - - if ( ber_get_int( ber, &along ) == LBER_ERROR ) { - return( LBER_ERROR ); - } - - return( ber_peek_tag( ber, &len )); -} - - -static void -merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr ) -{ - int i, j; -/* - * Merge error information in "lr" with "parentr" error code and string. - */ - if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) { - parentr->lr_res_errno = lr->lr_res_errno; - if ( lr->lr_res_error != NULL ) { - (void)append_referral( ld, &parentr->lr_res_error, - lr->lr_res_error ); - } - } else if ( lr->lr_res_errno != LDAP_SUCCESS && - parentr->lr_res_errno == LDAP_SUCCESS ) { - parentr->lr_res_errno = lr->lr_res_errno; - if ( parentr->lr_res_error != NULL ) { - free( parentr->lr_res_error ); - } - parentr->lr_res_error = lr->lr_res_error; - lr->lr_res_error = NULL; - if ( NAME_ERROR( lr->lr_res_errno )) { - if ( parentr->lr_res_matched != NULL ) { - free( parentr->lr_res_matched ); - } - parentr->lr_res_matched = lr->lr_res_matched; - lr->lr_res_matched = NULL; - } - if (lr->lr_ref_unfollowed != NULL){ - for (i=0;lr->lr_ref_unfollowed[i] != NULL; i++); - j = 0; - if (parentr->lr_ref_unfollowed != NULL){ - for (j=0;parentr->lr_ref_unfollowed[j]!= NULL ;j++); - j++; - } - parentr->lr_ref_unfollowed = (char **)realloc (parentr->lr_ref_unfollowed, (j+i+1) * sizeof(char *)); - if (parentr->lr_ref_unfollowed != NULL){ - for (i = 0; lr->lr_ref_unfollowed[i] != NULL; i++){ - parentr->lr_ref_unfollowed[j+i] = lr->lr_ref_unfollowed[i]; - lr->lr_ref_unfollowed[i] = NULL; - } - parentr->lr_ref_unfollowed[i+j+1] = NULL; - } else { - if (parentr->lr_res_errno == LDAP_SUCCESS) - parentr->lr_res_errno = LDAP_NO_MEMORY; - } - } - } - - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 236, "merged parent (id %1$d) error info: "), - parentr->lr_msgid, 0, 0 ); - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 237, "result errno %1$d, error <%2$s>, matched <%3$s>\n"), - parentr->lr_res_errno, - parentr->lr_res_error ? parentr->lr_res_error : "", - parentr->lr_res_matched ? parentr->lr_res_matched : "" ); -} - -#ifdef CLDAP -#if !defined( MACOS ) && !defined( DOS ) && !defined( _WIN32 ) -static int -ldap_select1( LDAP *ld, struct timeval *timeout ) -{ - fd_set readfds; - static int tblsize; - - if ( tblsize == 0 ) { -#ifdef USE_SYSCONF - tblsize = (int) sysconf( _SC_OPEN_MAX ); -#else /* USE_SYSCONF */ - tblsize = getdtablesize(); -#endif /* USE_SYSCONF */ - } - - FD_ZERO( &readfds ); - FD_SET( ld->ld_sb.sb_sd, &readfds ); - - return( select( tblsize, &readfds, 0, 0, timeout ) ); -} -#endif /* !MACOS */ - - -#ifdef MACOS -static int -ldap_select1( LDAP *ld, struct timeval *timeout ) -{ - return( tcpselect( ld->ld_sb.sb_sd, timeout )); -} -#endif /* MACOS */ - - -#if ( defined( DOS ) && defined( WINSOCK )) || defined( _WIN32 ) -static int -ldap_select1( LDAP *ld, struct timeval *timeout ) -{ - fd_set readfds; - int rc; - - FD_ZERO( &readfds ); - FD_SET( ld->ld_sb.sb_sd, &readfds ); - - rc = select( 1, &readfds, 0, 0, timeout ); - return( rc == SOCKET_ERROR ? -1 : rc ); -} -#endif /* WINSOCK || _WIN32 */ - - -#ifdef DOS -#ifdef PCNFS -static int -ldap_select1( LDAP *ld, struct timeval *timeout ) -{ - fd_set readfds; - int res; - - FD_ZERO( &readfds ); - FD_SET( ld->ld_sb.sb_sd, &readfds ); - - res = select( FD_SETSIZE, &readfds, NULL, NULL, timeout ); - if ( res == -1 && errno == EINTR) { - /* We've been CTRL-C'ed at this point. It'd be nice to - carry on but PC-NFS currently won't let us! */ - printf("\n*** CTRL-C ***\n"); - exit(-1); - } - return( res ); -} -#endif /* PCNFS */ - -#ifdef NCSA -static int -ldap_select1( LDAP *ld, struct timeval *timeout ) -{ - int rc; - clock_t endtime; - - if ( timeout != NULL ) { - endtime = timeout->tv_sec * CLK_TCK + - timeout->tv_usec * CLK_TCK / 1000000 + clock(); - } - - do { - Stask(); - rc = netqlen( ld->ld_sb.sb_sd ); - } while ( rc <= 0 && ( timeout == NULL || clock() < endtime )); - - return( rc > 0 ? 1 : 0 ); -} -#endif /* NCSA */ -#endif /* DOS */ -#endif /* CLDAP */ - - -int -ldap_msgfree( LDAPMessage *lm ) -{ - LDAPMessage *next; - int type = 0; - - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 238, "ldap_msgfree\n"), 0, 0, 0 ); - - for ( ; lm != NULLMSG; lm = next ) { - next = lm->lm_chain; - type = lm->lm_msgtype; - if (lm->lm_ber) - ber_free( lm->lm_ber, 1 ); - free( (char *) lm ); - } - - return( type ); -} - -/* - * ldap_msgdelete - delete a message. It returns: - * 0 if the entire message was deleted - * -1 if the message was not found, or only part of it was found - */ -int -ldap_msgdelete( LDAP *ld, int msgid ) -{ - LDAPMessage *lm, *prev; - -#ifdef _REENTRANT - LOCK_LDAP(ld); - LOCK_RESPONSE(ld); -#endif - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 239, "ldap_msgdelete\n"), 0, 0, 0 ); - - prev = NULLMSG; - for ( lm = ld->ld_responses; lm != NULLMSG; lm = lm->lm_next ) { - if ( lm->lm_msgid == msgid ) - break; - prev = lm; - } - - if ( lm == NULLMSG ) { -#ifdef _REENTRANT - UNLOCK_LDAP(ld); - UNLOCK_RESPONSE(ld); -#endif - return( -1 ); - } - - if ( prev == NULLMSG ) - ld->ld_responses = lm->lm_next; - else - prev->lm_next = lm->lm_next; - - if ( ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY ) { -#ifdef _REENTRANT - UNLOCK_LDAP(ld); - UNLOCK_RESPONSE(ld); -#endif - return( -1 ); - } - -#ifdef _REENTRANT - UNLOCK_LDAP(ld); - UNLOCK_RESPONSE(ld); -#endif - return( 0 ); -} - - -/* - * return 1 if message msgid is waiting to be abandoned, 0 otherwise - */ -static int -ldap_abandoned( LDAP *ld, int msgid ) -{ - int i; - - if ( ld == NULL ) return(1); - if ( ld->ld_abandoned == NULL ) - return( 0 ); - - for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) - if ( ld->ld_abandoned[i] == msgid ) - return( 1 ); - - return( 0 ); -} - - -static int -ldap_mark_abandoned( LDAP *ld, int msgid ) -{ - int i; - - if ( ld->ld_abandoned == NULL ) - return( -1 ); - - for ( i = 0; ld->ld_abandoned[i] != -1; i++ ) - if ( ld->ld_abandoned[i] == msgid ) - break; - - if ( ld->ld_abandoned[i] == -1 ) - return( -1 ); - - for ( ; ld->ld_abandoned[i] != -1; i++ ) { - ld->ld_abandoned[i] = ld->ld_abandoned[i + 1]; - } - - return( 0 ); -} - - -#ifdef CLDAP -int -cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber ) -{ - int rc; - unsigned int tag, len; - -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - if ( ld->ld_sb.sb_ber.ber_ptr >= ld->ld_sb.sb_ber.ber_end ) { - rc = ldap_select1( ld, timeout ); - if ( rc == -1 || rc == 0 ) { - ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN : - LDAP_TIMEOUT); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return( rc ); - } - } - - /* get the next message */ - if ( (tag = ber_get_next( &ld->ld_sb, &len, ber )) - != LDAP_TAG_MESSAGE ) { - ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : - LDAP_LOCAL_ERROR); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return( -1 ); - } - -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return( tag ); -} -#endif /* CLDAP */ - -/* ldapv3 API extensions */ - -int ldap_msgtype(LDAPMessage *res) -{ - if (res == NULL) - return (LDAP_RES_ANY); - return (res->lm_msgtype); -} - - -int ldap_msgid(LDAPMessage *res) -{ - if (res == NULL) - return (LDAP_RES_ANY); - return (res->lm_msgid); -} - -int ldap_parse_result(LDAP *ld, LDAPMessage *res, int *errcodep, char **matcheddnp, - char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp, - int freeit) -{ - LDAPMessage *lm; - BerElement ber; - unsigned int alen; - int along; - unsigned int tag; - int i; - size_t rc; - char * acharp = NULL, * a2ndcharp = NULL; - char ** arefs = NULL; - - Debug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 ); - - if (res == NULLMSG) - return (LDAP_PARAM_ERROR); - - if (matcheddnp && *matcheddnp){ - free(*matcheddnp); - *matcheddnp = NULL; - } - if (errmsgp && *errmsgp){ - free(*errmsgp); - *errmsgp = NULL; - } - if (referralsp && *referralsp){ - free_strarray(*referralsp); - *referralsp = NULL; - } - - if (serverctrlsp && *serverctrlsp){ - ldap_controls_free(*serverctrlsp); - *serverctrlsp = NULL; - } - - for (lm = res; lm->lm_chain != NULL; lm = lm->lm_chain) - - if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY - && lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE) - break; - - ber = *(lm->lm_ber); - -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - if (ld->ld_version == LDAP_VERSION3) { - rc = ber_scanf( &ber, "{iaa", &along, &acharp, &a2ndcharp); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - if (matcheddnp) { - *matcheddnp = acharp; - } else { - ldap_memfree(acharp); - } - if (errmsgp) { - *errmsgp = a2ndcharp; - } else { - ldap_memfree(a2ndcharp); - } - - if (errcodep) { - *errcodep = along; - } - - if (along == LDAP_REFERRAL){ - if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_REFERRAL) { - rc = ber_scanf(&ber, "{v}", &arefs); - if (rc == LBER_ERROR){ - /* try to free other stuff */ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - if (referralsp) { - *referralsp = arefs; - } else { - for (i = 0; arefs[i] != NULL; i++) - ldap_memfree(arefs[i]); - ldap_memfree((char *)arefs); - } - } else { - /* referral errcode without URL is forbiden */ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - } - rc = ber_scanf(&ber, "}"); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - /* It's the end of the result but the PDU may have controls */ - if (serverctrlsp && (ber_peek_tag(&ber, &alen) == LDAP_TAG_CONTROL_LIST)) { - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 392, "Controls found in result\n"), 0, 0, 0 ); - *serverctrlsp = ldap_controls_decode(&ber, - (int *)&rc); - if (*serverctrlsp == NULL) { - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - } else { - Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 393, "NO controls found in result\n"), 0, 0, 0 ); - } - } - else if (ld->ld_version == LDAP_VERSION2) { - rc = ber_scanf( &ber, "{iaa}", &along, &acharp, - &a2ndcharp ); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - if (matcheddnp) { - *matcheddnp = acharp; - } else { - ldap_memfree(acharp); - } - if (errmsgp) { - *errmsgp = a2ndcharp; - } else { - ldap_memfree(a2ndcharp); - } - if (errcodep) { - *errcodep = along; - } - } - else { - rc = ber_scanf( &ber, "{ia}", &along, &a2ndcharp ); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - - if (errmsgp) { - *errmsgp = a2ndcharp; - } else { - ldap_memfree(a2ndcharp); - } - if (errcodep) { - *errcodep = along; - } - } - - if ( freeit ) - ldap_msgfree(res); - -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_SUCCESS); -} - -int ldap_parse_sasl_bind_result(LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit) -{ - LDAPMessage *lm; - BerElement ber; - int along; - unsigned int tag; - int i; - size_t rc; - char * acharp = NULL, *a2ndcharp = NULL; - char ** arefs = NULL; - struct berval * creds = NULL; - - Debug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 ); - - if (res == NULLMSG) - return (LDAP_PARAM_ERROR); - -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - if ((res->lm_msgtype != LDAP_RES_BIND) || (ld->ld_version != LDAP_VERSION3)){ - ld->ld_errno = LDAP_PARAM_ERROR; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_PARAM_ERROR); - } -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - - ber = *(res->lm_ber); - rc = ber_scanf( &ber, "{iaa", &along, &acharp, &a2ndcharp); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - ld->ld_errno = LDAP_DECODING_ERROR; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - ldap_memfree(acharp); - ldap_memfree(a2ndcharp); - if (along == LDAP_SUCCESS || along == LDAP_SASL_BIND_INPROGRESS){ - /* Decode the serverSaslCreds if any */ - if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_SASLCREDS) { - rc = ber_get_stringal( &ber, &creds); - if (rc == LBER_ERROR ){ - if (freeit) - ldap_msgfree(res); -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - ld->ld_errno = LDAP_DECODING_ERROR; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - if (servercredp) { - *servercredp = creds; - } else { - ber_bvfree( creds ); - } - } - } else if (along == LDAP_REFERRAL) { - if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_REFERRAL){ - rc = ber_scanf(&ber, "{v}", &arefs); - if (rc == LBER_ERROR){ - /* try to free other stuff */ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - ld->ld_errno = LDAP_DECODING_ERROR; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - for (i = 0; arefs[i] != NULL; i++) - ldap_memfree(arefs[i]); - ldap_memfree((char *)arefs); - } else { - /* There should be at least one ref */ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - ld->ld_errno = LDAP_DECODING_ERROR; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - } - - rc = ber_scanf(&ber, "}"); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - ld->ld_errno = LDAP_DECODING_ERROR; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_DECODING_ERROR); - } - - if ( freeit ) - ldap_msgfree(res); -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - ld->ld_errno = along; -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (along); -} - -int ldap_parse_extended_result(LDAP *ld, LDAPMessage *res, char **resultoidp, - struct berval **resultdata, int freeit) -{ - LDAPMessage *lm; - BerElement ber; - int along; - unsigned int tag; - int i; - size_t rc; - char * acharp = NULL, *a2ndcharp = NULL, *anoid = NULL; - char **arefs = NULL; - struct berval * aresp = NULL; - - Debug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); - - if ( res == NULLMSG ) - return (LDAP_PARAM_ERROR); - -#ifdef _REENTRANT - LOCK_LDAP(ld); -#endif - if ((res->lm_msgtype != LDAP_RES_EXTENDED) || (ld->ld_version != LDAP_VERSION3)) - { - if ( res->lm_msgid != 0 ) -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - return (LDAP_PARAM_ERROR); - } -#ifdef _REENTRANT - UNLOCK_LDAP(ld); -#endif - - ber = *(res->lm_ber); - rc = ber_scanf( &ber, "{iaa", &along, &acharp, &a2ndcharp); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); - return (LDAP_DECODING_ERROR); - } - ldap_memfree(acharp); - ldap_memfree(a2ndcharp); - - if (along == LDAP_REFERRAL) { - if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_REFERRAL){ - rc = ber_scanf(&ber, "{v}", &arefs); - if (rc == LBER_ERROR){ - /* try to free other stuff */ - if (freeit) - ldap_msgfree( res ); - return (LDAP_DECODING_ERROR); - } - for (i = 0; arefs[i] != NULL; i++) - ldap_memfree(arefs[i]); - ldap_memfree((char *)arefs); - } else { - /* There should be at least one ref */ - if (freeit) - ldap_msgfree( res ); - return (LDAP_DECODING_ERROR); - } - } - - if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_EXT_RESPNAME) { - rc = ber_get_stringa( &ber, &anoid); - if (rc == LBER_ERROR ){ - if (freeit) - ldap_msgfree(res); - return (LDAP_DECODING_ERROR); - } - if (resultoidp) { - *resultoidp = anoid; - } else { - ldap_memfree( anoid ); - } - } - if (ber_peek_tag ( &ber, &tag) == LDAP_TAG_EXT_RESPONSE) { - rc = ber_get_stringal( &ber, &aresp); - if (rc == LBER_ERROR ){ - if (freeit) - ldap_msgfree(res); - return (LDAP_DECODING_ERROR); - } - if (resultdata) { - *resultdata = aresp; - } else { - ber_bvfree( aresp ); - } - } - - rc = ber_scanf(&ber, "}"); - if (rc == LBER_ERROR){ - if (freeit) - ldap_msgfree( res ); - return (LDAP_DECODING_ERROR); - } - - if ( freeit ) - ldap_msgfree(res); - - return (along); -} - - -static int Ref_AddToRequest(LDAPRequest *lr, char **refs) { - int count; - LDAPRef *lref; - LDAPRef *newRef; - - if ((newRef = (LDAPRef *)calloc(1, sizeof (LDAPRef))) == NULL){ - return LDAP_NO_MEMORY; - } - newRef->lref_refs = refs; - newRef->lref_next = NULL; - lref = lr->lr_references; - if (lref == NULL){ - lr->lr_references = newRef; - } else { - while (lref->lref_next != NULL) - lref = lref->lref_next; - lref->lref_next = newRef; - } - return LDAP_SUCCESS; -} - -static void Ref_FreeAll(LDAPRequest *lr) -{ - LDAPRef *lref, *next; - lref = lr->lr_references; - while (lref != NULL){ - next = lref->lref_next; - ldap_value_free(lref->lref_refs); - free (lref); - lref = next; - } - lr->lr_references = NULL; -} |