/*
* 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 */
#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 <errno.h>
#ifdef _AIX
#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
LDAPMessage **result );
LDAPMessage **result );
#ifdef CLDAP
#endif
#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 */
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
LDAPMessage **result )
{
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
#endif
/* look in the received responses */
/* if the msg has been abandonned, free it */
} else {
}
ldap_msgfree( lm );
continue;
}
/* If return ONE or RECEIVED message(s) or not a search result, return lm */
break;
/* Search in the set of messages if one is a search result */
break;
}
/* No, well wait for the result message */
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return( rv );
}
/* Here we have the Search result pointed by tmp */
break;
}
/* Check next response */
}
/* No response matching found : Wait for one */
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return( rv );
}
/* lm points to the message (chain) to return */
/* Remove message to return from ld_responses list */
} else {
}
} else {
} else {
}
}
if ( all == LDAP_MSG_ONE )
/* Otherwise return the whole chain */
/* No reponses attached */
#ifdef _REENTRANT
#endif
return( rv );
}
static int
LDAPMessage **result )
{
int rc;
#ifdef LDAP_DEBUG
0, 0, 0 );
} else {
}
#endif /* LDAP_DEBUG */
} else {
}
rc = -2;
while ( rc == -2 ) {
#ifdef LDAP_DEBUG
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
}
#endif /* LDAP_DEBUG */
/* A Message is available, decode and process it */
break;
}
}
/* There was no message available : Wait for one */
if ( rc == -1 ) {
errno, 0, 0 );
}
#endif
#else
#endif
if ( rc == -1 ) {
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
}
return( rc );
}
if ( rc == -1 ) {
} else {
rc = -2;
/* Check on each connection. */
if (is_ready > 0) {
/* A Message is available, decode and process it */
} else if ( is_ready < 0){
/* Error in the select : what to do in here ? */
/* So far : */
rc = -1;
}
}
}
}
}
/* 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 */
break;
}
}
}
return( rc );
}
static int
LDAPMessage **result )
{
int id;
int foundit = 0;
int retcode;
unsigned int lderr;
char *msgtypestr;
ber_zero_init( &ber, 0 );
/* get the next message */
!= LDAP_TAG_MESSAGE ) {
if ( tag == LBER_DEFAULT ) {
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
}
return( -1 );
}
/* message id */
return( -1 );
}
/* if it's been abandoned, toss it */
return( -2 ); /* continue looking */
}
/* the message type */
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"
*/
{
{
{
{
return(-1);
}
}
else
{
return(-1);
}
{
/* this field must be absent */
return(-1);
}
{
return(-1);
}
/* make a new ldap message to return the result */
{
return(-1);
}
(lderr==LDAP_PROTOCOL_ERROR) ||
(lderr==LDAP_UNAVAILABLE) )
{
/* make a new ldap message to return the result */
{
return(-1);
}
/* It is a notice of disconnection
* Return immediatly with an error code to stop
* reading any new message and to prevent the use
*/
return(-1);
}
else
{
/* This is another notification
* Keep on the processing of received messages
*/
goto read_from_sb;
}
}
else
{
Debug(LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1673, "Error while decoding Extended Response message"), NULL, NULL, NULL);
return(-1);
}
}
{
Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 229, "no request for response with msgid %ld (tossing)\n"), id, 0, 0 );
return( -2 ); /* continue looking */
}
if (tag == LDAP_RES_SEARCH_ENTRY)
else if (tag == LDAP_RES_SEARCH_REFERENCE)
else
/* REFERRALS HANDLING*/
refer_cnt = 0;
simple_request = 0;
hadref = 0;
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);
Debug ( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1284, "Error while decoding Search Reference Result message\n"),
rc = -1;
} else {
/* Store the referrals in request. We will follow them when the result arrives */
return (rc);
}
} else {
if (lderr == LDAP_PARTIAL_RESULTS){
/* Ldapv2 referrals */
} else if (lderr == LDAP_REFERRAL ){
/* We have some referrals, decode them */
}
} /* else error there should be at least one ref */
} else if (((lderr == LDAP_NO_SUCH_OBJECT) ||
(lderr == LDAP_UNAVAILABLE) ||
(lderr == LDAP_SERVER_DOWN) ||
(lderr == LDAP_CONNECT_ERROR)) &&
samereq = 1;
/* delete lr */
/* lr now points on parent request */
/* Follow referrals */
} else {
/* Here we have a simple result */
}
} else {
Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 1286, "Error while decoding result for request %$1d\n"),
}
}
total_count = 0;
/* Some search references pending... Let's try to chase them */
hadref = 1;
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 */
}
if (refer_cnt >= 0)
total_count += refer_cnt;
}
if (theErrCode != LDAP_SUCCESS) {
if (lr->lr_res_error)
}
}
}
/* if theRefs != NULL we have some referrals to chase, do it */
if (theRefs){
hadref = 1;
/* think about what to do */
}
if (refer_cnt >= 0)
total_count += refer_cnt;
if (samereq){ /* Just tried another referral for same request */
rc = -2;
/* continue */
}
if (retcode != LDAP_SUCCESS) {
if (lr->lr_res_error)
if (lr->lr_res_error)
}
}
} else if (theErrCode == LDAP_SUCCESS) {
/* no referral have been chased */
lr->lr_res_errno = (lderr == LDAP_PARTIAL_RESULTS || lderr == LDAP_REFERRAL) ? LDAP_SUCCESS : lderr;
}
}
if ( refer_cnt != 0 ) { /* chasing referrals */
if ( refer_cnt < 0 ) {
return( -1 ); /* fatal error */
}
/* We had a ref and we don't follow referral : Do nothing there ?! */
} else {
/* No referral chasing */
/* request without any referrals */
} else {
/* request with referrals or child request */
}
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, 0, 0 );
if ( !simple_request ) { /* We have to rebuild the result */
}
== LBER_ERROR ) {
}
}
}
}
}
}
return( rc );
}
/* End of REFERRALS */
/* make a new ldap message */
== NULL ) {
return( -1 );
}
#ifndef NO_CACHE
}
#endif /* NO_CACHE */
/* is this the one we're looking for? */
return( tag );
}
}
/*
* 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.
*/
break;
prev = l;
}
/* not part of an existing search response */
if ( l == NULLMSG ) {
if ( foundit ) { /* it a search result anyway, so return it */
return( tag );
}
return( -2 ); /* continue looking */
}
/* part of a search response - add to end of list of entries or references */
; /* NULL */
/* return the whole chain if that's what we were looking for */
if ( foundit ) {
else
*result = l;
return( l->lm_msgtype ); /* Patch 16 : was return(tag) */
}
return( -2 ); /* continue looking */
}
static int
{
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 );
return (LBER_ERROR);
}
return (LBER_ERROR);
}
return (LBER_ERROR);
}
} else {
return( LBER_ERROR );
}
}
return( LBER_ERROR );
}
return( LBER_ERROR );
}
}
static void
{
int i, j;
/*
* Merge error information in "lr" with "parentr" error code and string.
*/
lr->lr_res_error );
}
}
}
}
j = 0;
j++;
}
parentr->lr_ref_unfollowed = (char **)realloc (parentr->lr_ref_unfollowed, (j+i+1) * sizeof(char *));
}
} else {
}
}
}
Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 237, "result errno %1$d, error <%2$s>, matched <%3$s>\n"),
}
#ifdef CLDAP
static int
{
static int tblsize;
if ( tblsize == 0 ) {
#ifdef USE_SYSCONF
#else /* USE_SYSCONF */
tblsize = getdtablesize();
#endif /* USE_SYSCONF */
}
}
#endif /* !MACOS */
#ifdef MACOS
static int
{
}
#endif /* MACOS */
static int
{
int rc;
}
#endif /* WINSOCK || _WIN32 */
#ifdef DOS
#ifdef PCNFS
static int
{
int res;
/* 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
{
int rc;
}
do {
Stask();
return( rc > 0 ? 1 : 0 );
}
#endif /* NCSA */
#endif /* DOS */
#endif /* CLDAP */
int
{
int type = 0;
}
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
{
#ifdef _REENTRANT
#endif
break;
}
#ifdef _REENTRANT
#endif
return( -1 );
}
else
#ifdef _REENTRANT
#endif
return( -1 );
}
#ifdef _REENTRANT
#endif
return( 0 );
}
/*
* return 1 if message msgid is waiting to be abandoned, 0 otherwise
*/
static int
{
int i;
return( 0 );
return( 1 );
return( 0 );
}
static int
{
int i;
return( -1 );
break;
return( -1 );
}
return( 0 );
}
#ifdef CLDAP
int
{
int rc;
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return( rc );
}
}
/* get the next message */
!= LDAP_TAG_MESSAGE ) {
#ifdef _REENTRANT
#endif
return( -1 );
}
#ifdef _REENTRANT
#endif
return( tag );
}
#endif /* CLDAP */
/* ldapv3 API extensions */
{
return (LDAP_RES_ANY);
return (res->lm_msgtype);
}
{
return (LDAP_RES_ANY);
}
int freeit)
{
unsigned int alen;
int along;
unsigned int tag;
int i;
return (LDAP_PARAM_ERROR);
if (matcheddnp && *matcheddnp){
free(*matcheddnp);
*matcheddnp = NULL;
}
}
if (referralsp && *referralsp){
*referralsp = NULL;
}
if (serverctrlsp && *serverctrlsp){
*serverctrlsp = NULL;
}
break;
#ifdef _REENTRANT
#endif
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
if (matcheddnp) {
*matcheddnp = acharp;
} else {
}
if (errmsgp) {
} else {
}
if (errcodep) {
}
if (along == LDAP_REFERRAL){
if (rc == LBER_ERROR){
/* try to free other stuff */
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
if (referralsp) {
*referralsp = arefs;
} else {
ldap_memfree(arefs[i]);
ldap_memfree((char *)arefs);
}
} else {
/* referral errcode without URL is forbiden */
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
}
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
/* It's the end of the result but the PDU may have controls */
(int *)&rc);
if (*serverctrlsp == NULL) {
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
} else {
}
}
&a2ndcharp );
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
if (matcheddnp) {
*matcheddnp = acharp;
} else {
}
if (errmsgp) {
} else {
}
if (errcodep) {
}
}
else {
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
if (errmsgp) {
} else {
}
if (errcodep) {
}
}
if ( freeit )
#ifdef _REENTRANT
#endif
return (LDAP_SUCCESS);
}
int ldap_parse_sasl_bind_result(LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit)
{
int along;
unsigned int tag;
int i;
return (LDAP_PARAM_ERROR);
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (LDAP_PARAM_ERROR);
}
#ifdef _REENTRANT
#endif
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
/* Decode the serverSaslCreds if any */
if (rc == LBER_ERROR ){
if (freeit)
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
if (servercredp) {
*servercredp = creds;
} else {
ber_bvfree( creds );
}
}
} else if (along == LDAP_REFERRAL) {
if (rc == LBER_ERROR){
/* try to free other stuff */
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
ldap_memfree(arefs[i]);
ldap_memfree((char *)arefs);
} else {
/* There should be at least one ref */
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
}
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (LDAP_DECODING_ERROR);
}
if ( freeit )
#ifdef _REENTRANT
#endif
#ifdef _REENTRANT
#endif
return (along);
}
{
int along;
unsigned int tag;
int i;
return (LDAP_PARAM_ERROR);
#ifdef _REENTRANT
#endif
{
#ifdef _REENTRANT
#endif
return (LDAP_PARAM_ERROR);
}
#ifdef _REENTRANT
#endif
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
return (LDAP_DECODING_ERROR);
}
if (along == LDAP_REFERRAL) {
if (rc == LBER_ERROR){
/* try to free other stuff */
if (freeit)
ldap_msgfree( res );
return (LDAP_DECODING_ERROR);
}
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 (rc == LBER_ERROR ){
if (freeit)
return (LDAP_DECODING_ERROR);
}
if (resultoidp) {
*resultoidp = anoid;
} else {
ldap_memfree( anoid );
}
}
if (rc == LBER_ERROR ){
if (freeit)
return (LDAP_DECODING_ERROR);
}
if (resultdata) {
*resultdata = aresp;
} else {
ber_bvfree( aresp );
}
}
if (rc == LBER_ERROR){
if (freeit)
ldap_msgfree( res );
return (LDAP_DECODING_ERROR);
}
if ( freeit )
return (along);
}
int count;
return LDAP_NO_MEMORY;
}
} else {
}
return LDAP_SUCCESS;
}
{
}
}