10Sstevel@tonic-gate /*
20Sstevel@tonic-gate *
3*3857Sstevel * Copyright 1999 Sun Microsystems, Inc. All rights reserved.
4*3857Sstevel * Use is subject to license terms.
50Sstevel@tonic-gate *
60Sstevel@tonic-gate *
70Sstevel@tonic-gate * Comments:
80Sstevel@tonic-gate *
90Sstevel@tonic-gate */
100Sstevel@tonic-gate
110Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
120Sstevel@tonic-gate
130Sstevel@tonic-gate #include <stdio.h>
140Sstevel@tonic-gate #include <string.h>
150Sstevel@tonic-gate #include <sys/time.h>
160Sstevel@tonic-gate #include <sys/types.h>
170Sstevel@tonic-gate #include <sys/socket.h>
180Sstevel@tonic-gate #include <sys/errno.h>
190Sstevel@tonic-gate #include "portable.h"
200Sstevel@tonic-gate #include "lber.h"
210Sstevel@tonic-gate #include "ldap.h"
220Sstevel@tonic-gate #include "ldap-private.h"
230Sstevel@tonic-gate #include "ldap-int.h"
240Sstevel@tonic-gate
250Sstevel@tonic-gate static BerElement *
260Sstevel@tonic-gate re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *urldesc );
270Sstevel@tonic-gate static void addFollowedRef(LDAPRequest *lr, char *ref);
280Sstevel@tonic-gate static void addToFollowRef(LDAPRequest *lr, char *ref);
290Sstevel@tonic-gate static int addUnFollowedRef(LDAP *ld, LDAPRequest *lr, char *ref);
300Sstevel@tonic-gate
ldap_errormsg2referrals(char * errmsg)310Sstevel@tonic-gate char ** ldap_errormsg2referrals(char *errmsg) {
320Sstevel@tonic-gate char ** refs;
330Sstevel@tonic-gate int count;
340Sstevel@tonic-gate size_t len;
350Sstevel@tonic-gate char *p, *ref;
360Sstevel@tonic-gate
370Sstevel@tonic-gate if (errmsg == NULL){
380Sstevel@tonic-gate return (NULL);
390Sstevel@tonic-gate }
400Sstevel@tonic-gate len = strlen( errmsg );
410Sstevel@tonic-gate for ( p = errmsg; len >= LDAP_REF_STR_LEN; ++p, --len ) {
420Sstevel@tonic-gate if (( *p == 'R' || *p == 'r' ) && strncasecmp( p,
430Sstevel@tonic-gate LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) {
440Sstevel@tonic-gate *p = '\0';
450Sstevel@tonic-gate p += LDAP_REF_STR_LEN;
460Sstevel@tonic-gate break;
470Sstevel@tonic-gate }
480Sstevel@tonic-gate }
490Sstevel@tonic-gate
500Sstevel@tonic-gate if ( len < LDAP_REF_STR_LEN ) {
510Sstevel@tonic-gate return( NULL);
520Sstevel@tonic-gate }
530Sstevel@tonic-gate count = 1;
540Sstevel@tonic-gate ref = p;
550Sstevel@tonic-gate while ((ref = strchr(ref, '\n')) != NULL)
560Sstevel@tonic-gate count++;
570Sstevel@tonic-gate
580Sstevel@tonic-gate if ((refs = (char **)calloc(count + 1, sizeof(char *))) == NULL){
590Sstevel@tonic-gate return (NULL);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate
620Sstevel@tonic-gate count = 0;
630Sstevel@tonic-gate for (ref = p; ref != NULL; ref= p){
640Sstevel@tonic-gate if ((p = strchr(ref, '\n')) != NULL){
650Sstevel@tonic-gate *p = '\0';
660Sstevel@tonic-gate }
670Sstevel@tonic-gate refs[count++] = strdup(ref);
680Sstevel@tonic-gate if (p != NULL)
690Sstevel@tonic-gate *p++ = '\n';
700Sstevel@tonic-gate }
710Sstevel@tonic-gate return (refs);
720Sstevel@tonic-gate }
730Sstevel@tonic-gate
ldap_referral2error_msg(char ** refs)740Sstevel@tonic-gate char *ldap_referral2error_msg(char ** refs)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate int i;
770Sstevel@tonic-gate size_t len = 0;
780Sstevel@tonic-gate char *msg = NULL;
790Sstevel@tonic-gate
800Sstevel@tonic-gate if (refs == NULL)
810Sstevel@tonic-gate return (msg);
820Sstevel@tonic-gate
830Sstevel@tonic-gate for (i = 0; refs[i] != NULL; i++){
840Sstevel@tonic-gate len += strlen (refs[i]) + 1;
850Sstevel@tonic-gate }
860Sstevel@tonic-gate
870Sstevel@tonic-gate if ((len > 0) && ((msg = (char *)malloc(len + LDAP_REF_STR_LEN + 2)) != NULL)) {
880Sstevel@tonic-gate strncpy(msg, LDAP_REF_STR, LDAP_REF_STR_LEN);
890Sstevel@tonic-gate for (i = 0; refs[i] != NULL; i++) {
900Sstevel@tonic-gate strcat(msg, refs[i]);
910Sstevel@tonic-gate strcat(msg, "\n");
920Sstevel@tonic-gate }
930Sstevel@tonic-gate }
940Sstevel@tonic-gate return (msg);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate
980Sstevel@tonic-gate int
chase_referrals(LDAP * ld,LDAPRequest * lr,char ** refs,int * count,int samerequest)990Sstevel@tonic-gate chase_referrals( LDAP *ld, LDAPRequest *lr, char **refs, int *count, int samerequest )
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate int rc, len, newdn, i, j, refcnt, errCode;
1020Sstevel@tonic-gate char *p, *ports, *ref, *tmpref, *refdn;
1030Sstevel@tonic-gate LDAPRequest *origreq;
1040Sstevel@tonic-gate LDAPServer *srv;
1050Sstevel@tonic-gate BerElement *ber;
1060Sstevel@tonic-gate LDAPURLDesc *ludp;
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 215, "=> chase_referrals\n"), 0, 0, 0 );
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; /* optimistic */
1120Sstevel@tonic-gate *count = 0;
1130Sstevel@tonic-gate if ( refs == NULL ) {
1140Sstevel@tonic-gate return( LDAP_SUCCESS );
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate #ifdef _REENTRANT
1180Sstevel@tonic-gate LOCK_LDAP(ld);
1190Sstevel@tonic-gate #endif
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) {
1220Sstevel@tonic-gate Debug( LDAP_DEBUG_ANY,
1230Sstevel@tonic-gate catgets(slapdcat, 1, 216, "more than %d referral hops (dropping)\n"),
1240Sstevel@tonic-gate ld->ld_refhoplimit, 0, 0 );
1250Sstevel@tonic-gate /* XXX report as error in ld->ld_errno? */
1260Sstevel@tonic-gate rc = ld->ld_errno = (ld->ld_version >= LDAP_VERSION3) ? LDAP_REFERRAL_LIMIT_EXCEEDED : LDAP_OTHER;
1270Sstevel@tonic-gate #ifdef _REENTRANT
1280Sstevel@tonic-gate UNLOCK_LDAP(ld);
1290Sstevel@tonic-gate #endif
1300Sstevel@tonic-gate return( rc );
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /* find original request */
1340Sstevel@tonic-gate for ( origreq = lr; origreq->lr_parent != NULL;
1350Sstevel@tonic-gate origreq = origreq->lr_parent ) {
1360Sstevel@tonic-gate ;
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate for (refcnt = 0; refs[refcnt] != NULL; refcnt++)
1400Sstevel@tonic-gate ; /* Count number of referrals */
1410Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1277, "%d possible referrals to chase\n"), refcnt, 0,0);
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate rc = 0;
1440Sstevel@tonic-gate /* parse out & follow referrals */
1450Sstevel@tonic-gate for (i = 0; rc == 0 && refs[i] != NULL; i++) {
1460Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Try to chase %s\n"), refs[i], 0,0);
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /* Parse URL */
1490Sstevel@tonic-gate if (ldap_url_parse(refs[i], &ludp) != 0){
1500Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Bad URL for referral %s\n"), refs[i], 0,0);
1510Sstevel@tonic-gate errCode = LDAP_PARAM_ERROR;
1520Sstevel@tonic-gate addUnFollowedRef(ld, lr, refs[i]);
1530Sstevel@tonic-gate /* try next URL */
1540Sstevel@tonic-gate continue;
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /* Encode previous request with new URL */
1580Sstevel@tonic-gate if (( ber = re_encode_request( ld, origreq->lr_ber, ++ld->ld_msgid, ludp )) == NULL ) {
1590Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Error while encoding request for referral\n"), 0, 0,0);
1600Sstevel@tonic-gate ldap_free_urldesc(ludp);
1610Sstevel@tonic-gate errCode = ld->ld_errno;
1620Sstevel@tonic-gate addUnFollowedRef(ld, lr, refs[i]);
1630Sstevel@tonic-gate /* try next URL */
1640Sstevel@tonic-gate continue;
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer ))) == NULL ) {
1680Sstevel@tonic-gate ldap_free_urldesc(ludp);
1690Sstevel@tonic-gate ber_free( ber, 1 );
1700Sstevel@tonic-gate rc = ld->ld_errno = LDAP_NO_MEMORY;
1710Sstevel@tonic-gate #ifdef _REENTRANT
1720Sstevel@tonic-gate UNLOCK_LDAP(ld);
1730Sstevel@tonic-gate #endif
1740Sstevel@tonic-gate return( rc );
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate if (( srv->lsrv_host = strdup( ludp->lud_host ? ludp->lud_host : ld->ld_defhost)) == NULL ) {
1780Sstevel@tonic-gate ldap_free_urldesc(ludp);
1790Sstevel@tonic-gate free( (char *)srv );
1800Sstevel@tonic-gate ber_free( ber, 1 );
1810Sstevel@tonic-gate rc = ld->ld_errno = LDAP_NO_MEMORY;
1820Sstevel@tonic-gate #ifdef _REENTRANT
1830Sstevel@tonic-gate UNLOCK_LDAP(ld);
1840Sstevel@tonic-gate #endif
1850Sstevel@tonic-gate return( rc );
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate srv->lsrv_port = ludp->lud_port ? ludp->lud_port : LDAP_PORT;
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate if ( srv != NULL && send_server_request( ld, ber, ld->ld_msgid,
1910Sstevel@tonic-gate lr, srv, NULL, 1 ) >= 0 ) {
1920Sstevel@tonic-gate ++*count;
1930Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "Request has been forwarded to %s\n"), refs[i], 0,0);
1940Sstevel@tonic-gate addFollowedRef(lr, refs[i]);
1950Sstevel@tonic-gate for (j = i+1; refs[j] != NULL; j++){
1960Sstevel@tonic-gate addToFollowRef(lr, refs[j]);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate ldap_free_urldesc(ludp);
1990Sstevel@tonic-gate break;
2000Sstevel@tonic-gate } else {
2010Sstevel@tonic-gate Debug( LDAP_DEBUG_ANY,
2020Sstevel@tonic-gate catgets(slapdcat, 1, 220, "Unable to chase referral (%s)\n"),
2030Sstevel@tonic-gate ldap_err2string( ld->ld_errno ), 0, 0 );
2040Sstevel@tonic-gate addUnFollowedRef(ld, lr, refs[i]);
2050Sstevel@tonic-gate errCode = ld->ld_errno;
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate ldap_free_urldesc(ludp); /* So far spawn all requests */
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate #ifdef _REENTRANT
2110Sstevel@tonic-gate UNLOCK_LDAP(ld);
2120Sstevel@tonic-gate #endif
2130Sstevel@tonic-gate if (refs[i] != NULL) {
2140Sstevel@tonic-gate rc = LDAP_SUCCESS;
2150Sstevel@tonic-gate } else {
2160Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, catgets(slapdcat, 1, -1, "No referral was successfully chased (last error %d)\n"), errCode, 0, 0);
2170Sstevel@tonic-gate rc = errCode;
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate Debug ( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 1278, "<= chase_referrals --- \n"), 0,0,0);
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate return( rc );
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate
addFollowedRef(LDAPRequest * lr,char * ref)2240Sstevel@tonic-gate static void addFollowedRef(LDAPRequest *lr, char *ref)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate int i;
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate if (lr->lr_ref_followed == NULL){
2290Sstevel@tonic-gate if ((lr->lr_ref_followed = (char **)calloc(2, sizeof(char*))) == NULL)
2300Sstevel@tonic-gate return;
2310Sstevel@tonic-gate i = 0;
2320Sstevel@tonic-gate } else {
2330Sstevel@tonic-gate for (i = 0; lr->lr_ref_followed[i] != NULL; i++);
2340Sstevel@tonic-gate if ((lr->lr_ref_followed = (char **)realloc((char *)lr->lr_ref_followed, (i+2) * sizeof(char *))) == NULL){
2350Sstevel@tonic-gate return;
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate lr->lr_ref_followed[i++] = strdup(ref);
2390Sstevel@tonic-gate lr->lr_ref_followed[i] = NULL;
2400Sstevel@tonic-gate return;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
addToFollowRef(LDAPRequest * lr,char * ref)2430Sstevel@tonic-gate static void addToFollowRef(LDAPRequest *lr, char *ref)
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate int i;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate if (lr->lr_ref_tofollow == NULL){
2480Sstevel@tonic-gate if ((lr->lr_ref_tofollow = (char **)calloc(2, sizeof(char*))) == NULL)
2490Sstevel@tonic-gate return;
2500Sstevel@tonic-gate i = 0;
2510Sstevel@tonic-gate } else {
2520Sstevel@tonic-gate for (i = 0; lr->lr_ref_tofollow[i] != NULL; i++);
2530Sstevel@tonic-gate if ((lr->lr_ref_tofollow = (char **)realloc((char *)lr->lr_ref_tofollow, (i+2) * sizeof(char *))) == NULL){
2540Sstevel@tonic-gate return;
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate lr->lr_ref_tofollow[i++] = strdup(ref);
2580Sstevel@tonic-gate lr->lr_ref_tofollow[i] = NULL;
2590Sstevel@tonic-gate return;
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate
addUnFollowedRef(LDAP * ld,LDAPRequest * lr,char * ref)2620Sstevel@tonic-gate static int addUnFollowedRef(LDAP *ld, LDAPRequest *lr, char *ref)
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate int i;
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate if (lr->lr_ref_unfollowed == NULL){
2670Sstevel@tonic-gate if ((lr->lr_ref_unfollowed = (char **)calloc(2, sizeof(char*))) == NULL){
2680Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY;
2690Sstevel@tonic-gate return (-1);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate i = 0;
2720Sstevel@tonic-gate } else {
2730Sstevel@tonic-gate for (i = 0; lr->lr_ref_unfollowed[i] != NULL; i++);
2740Sstevel@tonic-gate if ((lr->lr_ref_unfollowed = (char **)realloc((char *)lr->lr_ref_unfollowed, (i+2) * sizeof(char *))) == NULL){
2750Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY;
2760Sstevel@tonic-gate return (-1);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate lr->lr_ref_unfollowed[i++] = strdup(ref);
2800Sstevel@tonic-gate lr->lr_ref_unfollowed[i] = NULL;
2810Sstevel@tonic-gate return (0);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate int
append_referral(LDAP * ld,char ** referralsp,char * s)2860Sstevel@tonic-gate append_referral( LDAP *ld, char **referralsp, char *s )
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate int first;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate if ( *referralsp == NULL ) {
2910Sstevel@tonic-gate first = 1;
2920Sstevel@tonic-gate *referralsp = (char *)malloc( strlen( s ) + LDAP_REF_STR_LEN
2930Sstevel@tonic-gate + 1 );
2940Sstevel@tonic-gate } else {
2950Sstevel@tonic-gate first = 0;
2960Sstevel@tonic-gate *referralsp = (char *)realloc( *referralsp,
2970Sstevel@tonic-gate strlen( *referralsp ) + strlen( s ) + 2 );
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate if ( *referralsp == NULL ) {
3010Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY;
3020Sstevel@tonic-gate return( -1 );
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate if ( first ) {
3060Sstevel@tonic-gate strcpy( *referralsp, LDAP_REF_STR );
3070Sstevel@tonic-gate } else {
3080Sstevel@tonic-gate strcat( *referralsp, "\n" );
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate strcat( *referralsp, s );
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate return( 0 );
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate static BerElement *
re_encode_request(LDAP * ld,BerElement * origber,int msgid,LDAPURLDesc * urldesc)3180Sstevel@tonic-gate re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *urldesc )
3190Sstevel@tonic-gate {
3200Sstevel@tonic-gate /*
3210Sstevel@tonic-gate * XXX this routine knows way too much about how the lber library works!
3220Sstevel@tonic-gate */
3230Sstevel@tonic-gate unsigned int along, tag, len;
3240Sstevel@tonic-gate int ver, scope, deref, sizelimit, timelimit, attrsonly;
3250Sstevel@tonic-gate int rc, hasCtrls;
3260Sstevel@tonic-gate BerElement tmpber, *ber;
3270Sstevel@tonic-gate char *dn, *seqstart;
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE,
3300Sstevel@tonic-gate catgets(slapdcat, 1, 221, "re_encode_request: new msgid %1$d, new dn <%2$s>\n"),
3310Sstevel@tonic-gate msgid, ( urldesc->lud_dn == NULL ) ? "NONE" : urldesc->lud_dn, 0 );
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate tmpber = *origber;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate * all LDAP requests are sequences that start with a message id,
3370Sstevel@tonic-gate * followed by a sequence that is tagged with the operation code
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate /* Bad assumption : delete op is not a sequence.
3400Sstevel@tonic-gate * So we have a special processing for it : it's much simpler
3410Sstevel@tonic-gate */
3420Sstevel@tonic-gate if ( ber_scanf( &tmpber, "{i", &along ) != LDAP_TAG_MSGID ||
3430Sstevel@tonic-gate ( tag = ber_peek_tag( &tmpber, &along )) == LBER_DEFAULT ) {
3440Sstevel@tonic-gate ld->ld_errno = LDAP_DECODING_ERROR;
3450Sstevel@tonic-gate return( NULL );
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /* Special case : delete request is not a sequence of... */
3490Sstevel@tonic-gate if (tag == LDAP_REQ_EXTENDED){
3500Sstevel@tonic-gate /* return error, I don't know how to do it automatically */
3510Sstevel@tonic-gate ld->ld_errno = LDAP_NOT_SUPPORTED;
3520Sstevel@tonic-gate return (NULL);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
3560Sstevel@tonic-gate return (NULL);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate if (tag == LDAP_REQ_DELETE) {
3600Sstevel@tonic-gate if ( ber_get_stringa( &tmpber, &dn ) == LBER_DEFAULT ) {
3610Sstevel@tonic-gate ld->ld_errno = LDAP_DECODING_ERROR;
3620Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE,
3630Sstevel@tonic-gate catgets(slapdcat, 1, 1279,"Error in decoding delete DN"),0,0,0);
3640Sstevel@tonic-gate ber_free( ber, 1);
3650Sstevel@tonic-gate return( NULL );
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate /* Check if controls */
3680Sstevel@tonic-gate hasCtrls = 0;
3690Sstevel@tonic-gate if (ber_peek_tag(&tmpber, &len) == LDAP_TAG_CONTROL_LIST){
3700Sstevel@tonic-gate hasCtrls = 1;
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate if ( urldesc->lud_dn && *urldesc->lud_dn ) {
3740Sstevel@tonic-gate free( dn );
3750Sstevel@tonic-gate dn = urldesc->lud_dn;
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate if ( ber_printf( ber, "{its", msgid, tag, dn ) == -1 ) {
3780Sstevel@tonic-gate Debug(LDAP_DEBUG_TRACE, "Error in re_encoding delete request",0,0,0);
3790Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
3800Sstevel@tonic-gate ber_free( ber, 1 );
3810Sstevel@tonic-gate return (NULL);
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate /* Now add controls if any */
3840Sstevel@tonic-gate if (hasCtrls && ber_write( ber, tmpber.ber_ptr, len, 0 ) != len ) {
3850Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
3860Sstevel@tonic-gate ber_free( ber, 1 );
3870Sstevel@tonic-gate return( NULL );
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate if (ber_printf( ber, "}" ) == -1 ) {
3900Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
3910Sstevel@tonic-gate ber_free( ber, 1 );
3920Sstevel@tonic-gate return( NULL );
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate #ifdef LDAP_DEBUG
3960Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
3970Sstevel@tonic-gate Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 222, "re_encode_request new request is:\n"),
3980Sstevel@tonic-gate 0, 0, 0 );
3990Sstevel@tonic-gate ber_dump( ber, 0 );
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate #endif /* LDAP_DEBUG */
4020Sstevel@tonic-gate return (ber);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if (( tag = ber_skip_tag( &tmpber, &along )) == LBER_DEFAULT ) {
4060Sstevel@tonic-gate ld->ld_errno = LDAP_DECODING_ERROR;
4070Sstevel@tonic-gate return( NULL );
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate /* Keep length and pointer */
4100Sstevel@tonic-gate seqstart = tmpber.ber_ptr;
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate /* bind requests have a version number before the DN & other stuff */
4130Sstevel@tonic-gate if ( tag == LDAP_REQ_BIND && ber_get_int( &tmpber, &ver ) ==
4140Sstevel@tonic-gate LBER_DEFAULT ) {
4150Sstevel@tonic-gate ld->ld_errno = LDAP_DECODING_ERROR;
4160Sstevel@tonic-gate ber_free( ber, 1 );
4170Sstevel@tonic-gate return( NULL );
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate /* the rest of the request is the DN followed by other stuff */
4210Sstevel@tonic-gate if ( ber_get_stringa( &tmpber, &dn ) == LBER_DEFAULT ) {
4220Sstevel@tonic-gate ber_free( ber, 1 );
4230Sstevel@tonic-gate return( NULL );
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate if ( urldesc->lud_dn != NULL ) {
4260Sstevel@tonic-gate free( dn );
4270Sstevel@tonic-gate dn = urldesc->lud_dn;
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate /* see what to do with CONTROLS */
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate if ( tag == LDAP_REQ_BIND ) {
4330Sstevel@tonic-gate rc = ber_printf( ber, "{it{is", msgid, tag, ver, dn );
4340Sstevel@tonic-gate } else {
4350Sstevel@tonic-gate rc = ber_printf( ber, "{it{s", msgid, tag, dn );
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate if ( rc == -1 ) {
4390Sstevel@tonic-gate ber_free( ber, 1 );
4400Sstevel@tonic-gate return( NULL );
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate if (tag == LDAP_REQ_SEARCH) {
4440Sstevel@tonic-gate /* Now for SEARCH, decode more of the request */
4450Sstevel@tonic-gate if (ber_scanf(&tmpber, "iiiib", &scope, &deref, &sizelimit, &timelimit, &attrsonly) == LBER_DEFAULT){
4460Sstevel@tonic-gate ld->ld_errno = LDAP_DECODING_ERROR;
4470Sstevel@tonic-gate ber_free( ber, 1 );
4480Sstevel@tonic-gate return( NULL );
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate if (ber_printf(ber, "iiiib", urldesc->lud_scope == LDAP_SCOPE_UNKNOWN ? scope : urldesc->lud_scope,
4510Sstevel@tonic-gate deref, sizelimit, timelimit, attrsonly) == -1) {
4520Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
4530Sstevel@tonic-gate ber_free( ber, 1 );
4540Sstevel@tonic-gate return( NULL );
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate /* We should then decode and check the filter as opposed to ludp->lud_filter */
4570Sstevel@tonic-gate /* Same for attributes */
4580Sstevel@tonic-gate /* Later */
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate /* The rest is the same for all requests */
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate /* Copy Buffer from tmpber.ber_ptr for along - (tmpber.ber_ptr - seqstart) */
4630Sstevel@tonic-gate /* It's the rest of the request */
4640Sstevel@tonic-gate len = along - ( tmpber.ber_ptr - seqstart);
4650Sstevel@tonic-gate if ( ber_write( ber, tmpber.ber_ptr, len, 0) != len ||
4660Sstevel@tonic-gate ber_printf( ber, "}" ) == -1 ) {
4670Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
4680Sstevel@tonic-gate ber_free( ber, 1 );
4690Sstevel@tonic-gate return( NULL );
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate if (seqstart + along < tmpber.ber_end){ /* there's probably some controls, copy them also */
4730Sstevel@tonic-gate len = tmpber.ber_end - seqstart - along;
4740Sstevel@tonic-gate if ( ber_write( ber, seqstart + along, len, 0) != len ){
4750Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
4760Sstevel@tonic-gate ber_free( ber, 1 );
4770Sstevel@tonic-gate return( NULL );
4780Sstevel@tonic-gate }
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate if ( ber_printf(ber, "}") == -1) {
4820Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR;
4830Sstevel@tonic-gate ber_free( ber, 1 );
4840Sstevel@tonic-gate return( NULL );
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate #ifdef LDAP_DEBUG
4880Sstevel@tonic-gate if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
4890Sstevel@tonic-gate Debug( LDAP_DEBUG_ANY, catgets(slapdcat, 1, 222, "re_encode_request new request is:\n"),
4900Sstevel@tonic-gate 0, 0, 0 );
4910Sstevel@tonic-gate ber_dump( ber, 0 );
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate #endif /* LDAP_DEBUG */
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate return( ber );
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate
4990Sstevel@tonic-gate LDAPRequest *
find_request_by_msgid(LDAP * ld,int msgid)5000Sstevel@tonic-gate find_request_by_msgid( LDAP *ld, int msgid )
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate LDAPRequest *lr;
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
5050Sstevel@tonic-gate if ( msgid == lr->lr_msgid ) {
5060Sstevel@tonic-gate break;
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate return( lr );
5110Sstevel@tonic-gate }
512