1 /* $NetBSD: references.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */
2
3 /* references.c */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 1998-2021 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 <sys/cdefs.h>
20 __RCSID("$NetBSD: references.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
21
22 #include "portable.h"
23
24 #include <stdio.h>
25
26 #include <ac/stdlib.h>
27
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "ldap-int.h"
33
34 LDAPMessage *
ldap_first_reference(LDAP * ld,LDAPMessage * chain)35 ldap_first_reference( LDAP *ld, LDAPMessage *chain )
36 {
37 assert( ld != NULL );
38 assert( LDAP_VALID( ld ) );
39 assert( chain != NULL );
40
41 return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE
42 ? chain
43 : ldap_next_reference( ld, chain );
44 }
45
46 LDAPMessage *
ldap_next_reference(LDAP * ld,LDAPMessage * ref)47 ldap_next_reference( LDAP *ld, LDAPMessage *ref )
48 {
49 assert( ld != NULL );
50 assert( LDAP_VALID( ld ) );
51 assert( ref != NULL );
52
53 for (
54 ref = ref->lm_chain;
55 ref != NULL;
56 ref = ref->lm_chain )
57 {
58 if( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
59 return( ref );
60 }
61 }
62
63 return( NULL );
64 }
65
66 int
ldap_count_references(LDAP * ld,LDAPMessage * chain)67 ldap_count_references( LDAP *ld, LDAPMessage *chain )
68 {
69 int i;
70
71 assert( ld != NULL );
72 assert( LDAP_VALID( ld ) );
73
74 for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
75 if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
76 i++;
77 }
78 }
79
80 return( i );
81 }
82
83 int
ldap_parse_reference(LDAP * ld,LDAPMessage * ref,char *** referralsp,LDAPControl *** serverctrls,int freeit)84 ldap_parse_reference(
85 LDAP *ld,
86 LDAPMessage *ref,
87 char ***referralsp,
88 LDAPControl ***serverctrls,
89 int freeit)
90 {
91 BerElement be;
92 char **refs = NULL;
93 int rc;
94
95 assert( ld != NULL );
96 assert( LDAP_VALID( ld ) );
97 assert( ref != NULL );
98
99 if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) {
100 return LDAP_PARAM_ERROR;
101 }
102
103 /* make a private copy of BerElement */
104 AC_MEMCPY(&be, ref->lm_ber, sizeof(be));
105
106 if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) {
107 rc = LDAP_DECODING_ERROR;
108 goto free_and_return;
109 }
110
111 if ( serverctrls == NULL ) {
112 rc = LDAP_SUCCESS;
113 goto free_and_return;
114 }
115
116 if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) {
117 rc = LDAP_DECODING_ERROR;
118 goto free_and_return;
119 }
120
121 rc = ldap_pvt_get_controls( &be, serverctrls );
122
123 free_and_return:
124
125 if( referralsp != NULL ) {
126 /* provide references regardless of return code */
127 *referralsp = refs;
128
129 } else {
130 LDAP_VFREE( refs );
131 }
132
133 if( freeit ) {
134 ldap_msgfree( ref );
135 }
136
137 if( rc != LDAP_SUCCESS ) {
138 ld->ld_errno = rc;
139
140 if( ld->ld_matched != NULL ) {
141 LDAP_FREE( ld->ld_matched );
142 ld->ld_matched = NULL;
143 }
144
145 if( ld->ld_error != NULL ) {
146 LDAP_FREE( ld->ld_error );
147 ld->ld_error = NULL;
148 }
149 }
150
151 return rc;
152 }
153