xref: /onnv-gate/usr/src/lib/libldap4/common/compare.c (revision 3857:21b9b714e4ab)
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