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