1 /*
2  * Copyright (c) 2001 by Sun Microsystems, Inc.
3  * All rights reserved.
4  */
5 
6 /*
7  * The contents of this file are subject to the Netscape Public
8  * License Version 1.1 (the "License"); you may not use this file
9  * except in compliance with the License. You may obtain a copy of
10  * the License at http://www.mozilla.org/NPL/
11  *
12  * Software distributed under the License is distributed on an "AS
13  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14  * implied. See the License for the specific language governing
15  * rights and limitations under the License.
16  *
17  * The Original Code is Mozilla Communicator client code, released
18  * March 31, 1998.
19  *
20  * The Initial Developer of the Original Code is Netscape
21  * Communications Corporation. Portions created by Netscape are
22  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
23  * Rights Reserved.
24  *
25  * Contributor(s):
26  */
27 /*
28  *  referral.c - routines for handling LDAPv3 referrals and references.
29  */
30 
31 #include "ldap-int.h"
32 
33 
34 LDAPMessage *
35 LDAP_CALL
ldap_first_reference(LDAP * ld,LDAPMessage * res)36 ldap_first_reference( LDAP *ld, LDAPMessage *res )
37 {
38 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || res == NULLMSG ) {
39 		return( NULLMSG );
40 	}
41 
42 	if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
43 		return( res );
44 	}
45 
46 	return( ldap_next_reference( ld, res ));
47 }
48 
49 
50 LDAPMessage *
51 LDAP_CALL
ldap_next_reference(LDAP * ld,LDAPMessage * ref)52 ldap_next_reference( LDAP *ld, LDAPMessage *ref )
53 {
54 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || ref == NULLMSG ) {
55 		return( NULLMSG );		/* punt */
56 	}
57 
58 	for ( ref = ref->lm_chain; ref != NULLMSG; ref = ref->lm_chain ) {
59 		if ( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
60 			return( ref );
61 		}
62 	}
63 
64 	return( NULLMSG );
65 }
66 
67 
68 int
69 LDAP_CALL
ldap_count_references(LDAP * ld,LDAPMessage * res)70 ldap_count_references( LDAP *ld, LDAPMessage *res )
71 {
72 	int	i;
73 
74 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
75 		return( -1 );
76 	}
77 
78 	for ( i = 0; res != NULL; res = res->lm_chain ) {
79 		if ( res->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
80 			++i;
81 		}
82 	}
83 
84 	return( i );
85 }
86 
87 
88 /*
89  * returns an LDAP error code.
90  */
91 int
92 LDAP_CALL
ldap_parse_reference(LDAP * ld,LDAPMessage * ref,char *** referralsp,LDAPControl *** serverctrlsp,int freeit)93 ldap_parse_reference( LDAP *ld, LDAPMessage *ref, char ***referralsp,
94     LDAPControl ***serverctrlsp, int freeit )
95 {
96 	int		err;
97 
98 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ||
99 	    !NSLDAPI_VALID_LDAPMESSAGE_REFERENCE_POINTER( ref )) {
100 		return( LDAP_PARAM_ERROR );
101 	}
102 
103 	err = nsldapi_parse_reference( ld, ref->lm_ber, referralsp,
104 		serverctrlsp );
105 
106 	LDAP_SET_LDERRNO( ld, err, NULL, NULL );
107 
108 	if ( freeit ) {
109 		ldap_msgfree( ref );
110 	}
111 
112 	return( err );
113 }
114 
115 
116 /*
117  * returns an LDAP error code indicating success or failure of parsing
118  * does NOT set any error information inside "ld"
119  */
120 int
nsldapi_parse_reference(LDAP * ld,BerElement * rber,char *** referralsp,LDAPControl *** serverctrlsp)121 nsldapi_parse_reference( LDAP *ld, BerElement *rber, char ***referralsp,
122     LDAPControl ***serverctrlsp )
123 {
124 	int		err;
125 	BerElement	ber;
126 	char		**refs;
127 
128 	/*
129 	 * Parse a searchResultReference message.  These are used in LDAPv3
130 	 * and beyond and look like this:
131 	 *
132 	 *	SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
133 	 *
134 	 * all wrapped up in an LDAPMessage sequence which looks like this:
135 	 *
136 	 *	LDAPMessage ::= SEQUENCE {
137 	 *		messageID	MessageID,
138 	 *		SearchResultReference
139 	 *		controls	[0] Controls OPTIONAL
140 	 *	}
141 	 *
142 	 * ldap_result() pulls out the message id, so by the time a result
143 	 * message gets here we are conveniently sitting at the start of the
144 	 * SearchResultReference itself.
145 	 */
146 	err = LDAP_SUCCESS;	/* optimistic */
147 	ber = *rber;		/* struct copy */
148 
149 	if ( ber_scanf( &ber, "{v", &refs ) == LBER_ERROR ) {
150 	    err = LDAP_DECODING_ERROR;
151 	} else if ( serverctrlsp != NULL ) {
152 	    /* pull out controls (if requested and any are present) */
153 	    if ( ber_scanf( &ber, "}" ) == LBER_ERROR ) {
154 		err = LDAP_DECODING_ERROR;
155 	    } else {
156 		err = nsldapi_get_controls( &ber, serverctrlsp );
157 	    }
158 	}
159 
160 	if ( referralsp == NULL ) {
161 	    ldap_value_free( refs );
162 	} else {
163 	    *referralsp = refs;
164 	}
165 
166 	return( err );
167 }
168 
169 #ifdef _SOLARIS_SDK
170 
ldap_get_reference_urls(LDAP * ld,LDAPMessage * res)171 char ** ldap_get_reference_urls(LDAP *ld, LDAPMessage *res)
172 {
173         BerElement tmp;
174         char **urls = NULL;
175 
176         LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_reference_urls\n", 0, 0, 0 );
177 
178         if (res == NULL){
179                 ld->ld_errno = LDAP_PARAM_ERROR;
180                 return (NULL);
181         }
182         tmp = *res->lm_ber; /* struct copy */
183         if ( ber_scanf( &tmp, "{v}", &urls) == LBER_ERROR){
184                 ld->ld_errno = LDAP_DECODING_ERROR;
185                 return (NULL);
186         }
187         return (urls);
188 }
189 
190 #endif /* _SOLARIS_SDK */
191 
192