1 /*	$NetBSD: references.c,v 1.1.1.3 2010/12/12 15:21:34 adam Exp $	*/
2 
3 /* references.c */
4 /* OpenLDAP: pkg/ldap/libraries/libldap/references.c,v 1.24.2.5 2010/04/13 20:22:59 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2010 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 #include "portable.h"
20 
21 #include <stdio.h>
22 
23 #include <ac/stdlib.h>
24 
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/time.h>
28 
29 #include "ldap-int.h"
30 
31 LDAPMessage *
32 ldap_first_reference( LDAP *ld, LDAPMessage *chain )
33 {
34 	assert( ld != NULL );
35 	assert( LDAP_VALID( ld ) );
36 	assert( chain != NULL );
37 
38 	return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE
39 		? chain
40 		: ldap_next_reference( ld, chain );
41 }
42 
43 LDAPMessage *
44 ldap_next_reference( LDAP *ld, LDAPMessage *ref )
45 {
46 	assert( ld != NULL );
47 	assert( LDAP_VALID( ld ) );
48 	assert( ref != NULL );
49 
50 	for (
51 		ref = ref->lm_chain;
52 		ref != NULL;
53 		ref = ref->lm_chain )
54 	{
55 		if( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
56 			return( ref );
57 		}
58 	}
59 
60 	return( NULL );
61 }
62 
63 int
64 ldap_count_references( LDAP *ld, LDAPMessage *chain )
65 {
66 	int	i;
67 
68 	assert( ld != NULL );
69 	assert( LDAP_VALID( ld ) );
70 
71 	for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
72 		if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
73 			i++;
74 		}
75 	}
76 
77 	return( i );
78 }
79 
80 int
81 ldap_parse_reference(
82 	LDAP            *ld,
83 	LDAPMessage     *ref,
84 	char            ***referralsp,
85 	LDAPControl     ***serverctrls,
86 	int             freeit)
87 {
88 	BerElement be;
89 	char **refs = NULL;
90 	int rc;
91 
92 	assert( ld != NULL );
93 	assert( LDAP_VALID( ld ) );
94 	assert( ref !=  NULL );
95 
96 	if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) {
97 		return LDAP_PARAM_ERROR;
98 	}
99 
100 	/* make a private copy of BerElement */
101 	AC_MEMCPY(&be, ref->lm_ber, sizeof(be));
102 
103 	if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) {
104 		rc = LDAP_DECODING_ERROR;
105 		goto free_and_return;
106 	}
107 
108 	if ( serverctrls == NULL ) {
109 		rc = LDAP_SUCCESS;
110 		goto free_and_return;
111 	}
112 
113 	if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) {
114 		rc = LDAP_DECODING_ERROR;
115 		goto free_and_return;
116 	}
117 
118 	rc = ldap_pvt_get_controls( &be, serverctrls );
119 
120 free_and_return:
121 
122 	if( referralsp != NULL ) {
123 		/* provide references regradless of return code */
124 		*referralsp = refs;
125 
126 	} else {
127 		LDAP_VFREE( refs );
128 	}
129 
130 	if( freeit ) {
131 		ldap_msgfree( ref );
132 	}
133 
134 	if( rc != LDAP_SUCCESS ) {
135 		ld->ld_errno = rc;
136 
137 		if( ld->ld_matched != NULL ) {
138 			LDAP_FREE( ld->ld_matched );
139 			ld->ld_matched = NULL;
140 		}
141 
142 		if( ld->ld_error != NULL ) {
143 			LDAP_FREE( ld->ld_error );
144 			ld->ld_error = NULL;
145 		}
146 	}
147 
148 	return rc;
149 }
150