1 /*
2 * Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * Copyright (c) 1990 Regents of the University of Michigan.
10 * All rights reserved.
11 *
12 * compare.c
13 */
14
15 #ifndef lint
16 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
17 #endif
18
19 #include <stdio.h>
20 #include <string.h>
21
22 #ifdef MACOS
23 #include "macos.h"
24 #endif /* MACOS */
25
26 #if !defined( MACOS ) && !defined( DOS )
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #endif
30
31 #include "lber.h"
32 #include "ldap.h"
33 #include "ldap-private.h"
34 #include "ldap-int.h"
35
ldap_build_compare_req(LDAP * ld,char * dn,char * attr,struct berval * bvalue,LDAPControl ** serverctrls)36 BerElement * ldap_build_compare_req(LDAP *ld, char *dn, char *attr,
37 struct berval *bvalue, LDAPControl **serverctrls)
38 {
39 BerElement *ber;
40 int rc, rv;
41
42 /* The compare request looks like this:
43 * CompareRequest ::= SEQUENCE {
44 * entry DistinguishedName,
45 * ava SEQUENCE {
46 * type AttributeType,
47 * value AttributeValue
48 * }
49 * }
50 * and must be wrapped in an LDAPMessage.
51 */
52 /* create a message to send */
53 if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
54 ld->ld_errno = LDAP_NO_MEMORY;
55 return( NULLBER );
56 }
57
58 if ( ber_printf( ber, "{it{s{so}}", ++ld->ld_msgid, LDAP_REQ_COMPARE,
59 dn, attr, bvalue->bv_val, bvalue->bv_len ) == -1 ) {
60 ld->ld_errno = LDAP_ENCODING_ERROR;
61 ber_free( ber, 1 );
62 return( NULLBER );
63 }
64
65 /* LDAPv3 */
66 /* Code controls if any */
67 if (serverctrls && serverctrls[0]) {
68 if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){
69 ld->ld_errno = LDAP_ENCODING_ERROR;
70 return( NULLBER );
71 }
72 } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) {
73 /* Otherwise, is there any global server ctrls ? */
74 if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){
75 ld->ld_errno = LDAP_ENCODING_ERROR;
76 return( NULLBER );
77 }
78 }
79 if (ber_printf(ber, "}") == -1) {
80 ld->ld_errno = LDAP_ENCODING_ERROR;
81 ber_free(ber, 1);
82 return (NULLBER);
83 }
84
85 return (ber);
86 }
87
88 /*
89 * ldap_compare - perform an ldap (and X.500) compare operation. The dn
90 * of the entry to compare to and the attribute and value to compare (in
91 * attr and value) are supplied. The msgid of the response is returned.
92 *
93 * Example:
94 * ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" )
95 */
96 int
ldap_compare(LDAP * ld,char * dn,char * attr,char * value)97 ldap_compare( LDAP *ld, char *dn, char *attr, char *value )
98 {
99 BerElement *ber;
100 struct berval bv;
101 int rv;
102
103 /* The compare request looks like this:
104 * CompareRequest ::= SEQUENCE {
105 * entry DistinguishedName,
106 * ava SEQUENCE {
107 * type AttributeType,
108 * value AttributeValue
109 * }
110 * }
111 * and must be wrapped in an LDAPMessage.
112 */
113
114 #ifdef _REENTRANT
115 LOCK_LDAP(ld);
116 #endif
117 Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 );
118
119 bv.bv_val = value;
120 bv.bv_len = strlen(value);
121
122 if ((ber = ldap_build_compare_req(ld, dn, attr, &bv, NULL)) == NULLBER) {
123 #ifdef _REENTRANT
124 UNLOCK_LDAP(ld);
125 #endif
126 return (-1);
127 }
128
129 #ifndef NO_CACHE
130 if ( ld->ld_cache != NULL ) {
131 if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) {
132 ber_free( ber, 1 );
133 ld->ld_errno = LDAP_SUCCESS;
134 #ifdef _REENTRANT
135 UNLOCK_LDAP(ld);
136 #endif
137 return( ld->ld_msgid );
138 }
139 add_request_to_cache( ld, LDAP_REQ_COMPARE, ber );
140 }
141 #endif /* NO_CACHE */
142
143 /* send the message */
144 rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber );
145 #ifdef _REENTRANT
146 UNLOCK_LDAP(ld);
147 #endif
148 return (rv);
149 }
150
151 int
ldap_compare_s(LDAP * ld,char * dn,char * attr,char * value)152 ldap_compare_s( LDAP *ld, char *dn, char *attr, char *value )
153 {
154 int msgid;
155 LDAPMessage *res;
156
157 if ( (msgid = ldap_compare( ld, dn, attr, value )) == -1 )
158 return( ld->ld_errno );
159
160 if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
161 return( ld->ld_errno );
162
163 return( ldap_result2error( ld, res, 1 ) );
164 }
165
166 /* LDAPv3 API extensions */
ldap_compare_ext(LDAP * ld,char * dn,char * attr,struct berval * bvalue,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int * msgidp)167 int ldap_compare_ext(LDAP *ld, char *dn, char *attr, struct berval *bvalue,
168 LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp)
169 {
170 BerElement *ber;
171 struct berval bv;
172 int rv;
173
174 /* The compare request looks like this:
175 * CompareRequest ::= SEQUENCE {
176 * entry DistinguishedName,
177 * ava SEQUENCE {
178 * type AttributeType,
179 * value AttributeValue
180 * }
181 * }
182 * and must be wrapped in an LDAPMessage.
183 */
184
185 #ifdef _REENTRANT
186 LOCK_LDAP(ld);
187 #endif
188 Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 );
189
190 if ((ber = ldap_build_compare_req(ld, dn, attr, bvalue, NULL)) == NULLBER) {
191 rv = ld->ld_errno;
192 if (rv == LDAP_SUCCESS)
193 rv = LDAP_OTHER;
194 #ifdef _REENTRANT
195 UNLOCK_LDAP(ld);
196 #endif
197 return (rv);
198 }
199
200 #ifndef NO_CACHE
201 if ( ld->ld_cache != NULL ) {
202 if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) {
203 ber_free( ber, 1 );
204 ld->ld_errno = LDAP_SUCCESS;
205 *msgidp = ld->ld_msgid;
206 #ifdef _REENTRANT
207 UNLOCK_LDAP(ld);
208 #endif
209 return( LDAP_SUCCESS );
210 }
211 add_request_to_cache( ld, LDAP_REQ_COMPARE, ber );
212 }
213 #endif /* NO_CACHE */
214
215 /* send the message */
216 rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber );
217 if (rv == -1) {
218 rv = ld->ld_errno;
219 if (rv == LDAP_SUCCESS){
220 rv = LDAP_OTHER;
221 }
222 #ifdef _REENTRANT
223 UNLOCK_LDAP(ld);
224 #endif
225 return (rv);
226 }
227
228 *msgidp = rv;
229 #ifdef _REENTRANT
230 UNLOCK_LDAP(ld);
231 #endif
232 return (LDAP_SUCCESS);
233 }
234
ldap_compare_ext_s(LDAP * ld,char * dn,char * attr,struct berval * bvalue,LDAPControl ** serverctrls,LDAPControl ** clientctrls)235 int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, struct berval *bvalue,
236 LDAPControl ** serverctrls, LDAPControl **clientctrls)
237 {
238 int msgid, retcode = LDAP_SUCCESS;
239 LDAPMessage *res;
240
241 if ( (retcode = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS )
242 return( retcode );
243
244 if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
245 return( ld->ld_errno );
246
247 #ifdef _REENTRANT
248 LOCK_LDAP(ld);
249 #endif
250 retcode = ldap_parse_result( ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error,
251 &ld->ld_referrals, &ld->ld_ret_ctrls, 1);
252 if (retcode == LDAP_SUCCESS)
253 retcode = ld->ld_errno;
254 #ifdef _REENTRANT
255 UNLOCK_LDAP(ld);
256 #endif
257 return (retcode);
258 }
259
260