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 16static 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 36BerElement * 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 */ 96int 97ldap_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 151int 152ldap_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 */ 167int 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 235int 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