1 /*
2  * The contents of this file are subject to the Netscape Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/NPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is Mozilla Communicator client code, released
13  * March 31, 1998.
14  *
15  * The Initial Developer of the Original Code is Netscape
16  * Communications Corporation. Portions created by Netscape are
17  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
18  * Rights Reserved.
19  *
20  * Contributor(s):
21  */
22 /*
23  *  Copyright (c) 1990 Regents of the University of Michigan.
24  *  All rights reserved.
25  */
26 /*
27  *  compare.c
28  */
29 
30 #if 0
31 #ifndef lint
32 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
33 #endif
34 #endif
35 
36 #include "ldap-int.h"
37 
38 /*
39  * ldap_compare - perform an ldap compare operation.  The dn
40  * of the entry to compare to and the attribute and value to compare (in
41  * attr and value) are supplied.  The msgid of the response is returned.
42  *
43  * Example:
44  *	ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" )
45  */
46 int
47 LDAP_CALL
ldap_compare(LDAP * ld,const char * dn,const char * attr,const char * value)48 ldap_compare( LDAP *ld, const char *dn, const char *attr, const char *value )
49 {
50 	int		msgid;
51 	struct berval	bv;
52 
53 	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_compare\n", 0, 0, 0 );
54 
55 	bv.bv_val = (char *)value;
56 	bv.bv_len = ( value == NULL ) ? 0 : strlen( value );
57 
58 	if ( ldap_compare_ext( ld, dn, attr, &bv, NULL, NULL, &msgid )
59 	    == LDAP_SUCCESS ) {
60 		return( msgid );
61 	} else {
62 		return( -1 );	/* error is in ld handle */
63 	}
64 }
65 
66 int
67 LDAP_CALL
ldap_compare_ext(LDAP * ld,const char * dn,const char * attr,const struct berval * bvalue,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int * msgidp)68 ldap_compare_ext( LDAP *ld, const char *dn, const char *attr,
69     const struct berval *bvalue, LDAPControl **serverctrls,
70     LDAPControl **clientctrls, int *msgidp )
71 {
72 	BerElement	*ber;
73 	int		rc, lderr;
74 
75 	/* The compare request looks like this:
76 	 *	CompareRequest ::= SEQUENCE {
77 	 *		entry	DistinguishedName,
78 	 *		ava	SEQUENCE {
79 	 *			type	AttributeType,
80 	 *			value	AttributeValue
81 	 *		}
82 	 *	}
83 	 * and must be wrapped in an LDAPMessage.
84 	 */
85 
86 	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_compare_ext\n", 0, 0, 0 );
87 
88 	if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
89 		return( LDAP_PARAM_ERROR );
90 	}
91 	if ( attr == NULL || bvalue == NULL || bvalue->bv_len == 0
92 	    || msgidp == NULL ) {
93 		lderr = LDAP_PARAM_ERROR;
94 		LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
95 		return( lderr );
96 	}
97 
98 	if ( dn == NULL ) {
99 		dn = "";
100 	}
101 
102 	LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
103 	*msgidp = ++ld->ld_msgid;
104 	LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
105 
106 	/* check the cache */
107 	if ( ld->ld_cache_on && ld->ld_cache_compare != NULL ) {
108 		LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
109 		if ( (rc = (ld->ld_cache_compare)( ld, *msgidp,
110 		    LDAP_REQ_COMPARE, dn, attr, bvalue )) != 0 ) {
111 			*msgidp = rc;
112 			LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
113 			return( LDAP_SUCCESS );
114 		}
115 		LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
116 	}
117 
118 	/* create a message to send */
119 	if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber ))
120 	    != LDAP_SUCCESS ) {
121 		return( lderr );
122 	}
123 
124 	if ( ber_printf( ber, "{it{s{so}}", *msgidp, LDAP_REQ_COMPARE, dn,
125 	    attr, bvalue->bv_val, (int)bvalue->bv_len /* XXX lossy cast */ )
126 	    == -1 ) {
127 		lderr = LDAP_ENCODING_ERROR;
128 		LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
129 		ber_free( ber, 1 );
130 		return( lderr );
131 	}
132 
133 	if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber ))
134 	    != LDAP_SUCCESS ) {
135 		ber_free( ber, 1 );
136 		return( lderr );
137 	}
138 
139 	/* send the message */
140 	rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_COMPARE,
141 		(char *)dn, ber );
142 	*msgidp = rc;
143 	return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
144 }
145 
146 int
147 LDAP_CALL
ldap_compare_s(LDAP * ld,const char * dn,const char * attr,const char * value)148 ldap_compare_s( LDAP *ld, const char *dn, const char *attr,
149     const char *value )
150 {
151 	struct berval	bv;
152 
153 	bv.bv_val = (char *)value;
154 	bv.bv_len = ( value == NULL ) ? 0 : strlen( value );
155 
156 	return( ldap_compare_ext_s( ld, dn, attr, &bv, NULL, NULL ));
157 }
158 
159 int
160 LDAP_CALL
ldap_compare_ext_s(LDAP * ld,const char * dn,const char * attr,const struct berval * bvalue,LDAPControl ** serverctrls,LDAPControl ** clientctrls)161 ldap_compare_ext_s( LDAP *ld, const char *dn, const char *attr,
162     const struct berval *bvalue, LDAPControl **serverctrls,
163     LDAPControl **clientctrls )
164 {
165 	int		err, msgid;
166 	LDAPMessage	*res;
167 
168 	if (( err = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls,
169 	    clientctrls, &msgid )) != LDAP_SUCCESS ) {
170 		return( err );
171 	}
172 
173 	if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res )
174 	    == -1 ) {
175 		return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
176 	}
177 
178 	return( ldap_result2error( ld, res, 1 ) );
179 }
180