10Sstevel@tonic-gate /* 2*3857Sstevel * Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved. 3*3857Sstevel * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate /* 90Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan. 100Sstevel@tonic-gate * All rights reserved. 110Sstevel@tonic-gate * 120Sstevel@tonic-gate * compare.c 130Sstevel@tonic-gate */ 140Sstevel@tonic-gate 150Sstevel@tonic-gate #ifndef lint 160Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; 170Sstevel@tonic-gate #endif 180Sstevel@tonic-gate 190Sstevel@tonic-gate #include <stdio.h> 200Sstevel@tonic-gate #include <string.h> 210Sstevel@tonic-gate 220Sstevel@tonic-gate #ifdef MACOS 230Sstevel@tonic-gate #include "macos.h" 240Sstevel@tonic-gate #endif /* MACOS */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #if !defined( MACOS ) && !defined( DOS ) 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/socket.h> 290Sstevel@tonic-gate #endif 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include "lber.h" 320Sstevel@tonic-gate #include "ldap.h" 330Sstevel@tonic-gate #include "ldap-private.h" 340Sstevel@tonic-gate #include "ldap-int.h" 350Sstevel@tonic-gate 360Sstevel@tonic-gate BerElement * ldap_build_compare_req(LDAP *ld, char *dn, char *attr, 370Sstevel@tonic-gate struct berval *bvalue, LDAPControl **serverctrls) 380Sstevel@tonic-gate { 390Sstevel@tonic-gate BerElement *ber; 400Sstevel@tonic-gate int rc, rv; 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* The compare request looks like this: 430Sstevel@tonic-gate * CompareRequest ::= SEQUENCE { 440Sstevel@tonic-gate * entry DistinguishedName, 450Sstevel@tonic-gate * ava SEQUENCE { 460Sstevel@tonic-gate * type AttributeType, 470Sstevel@tonic-gate * value AttributeValue 480Sstevel@tonic-gate * } 490Sstevel@tonic-gate * } 500Sstevel@tonic-gate * and must be wrapped in an LDAPMessage. 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate /* create a message to send */ 530Sstevel@tonic-gate if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) { 540Sstevel@tonic-gate ld->ld_errno = LDAP_NO_MEMORY; 550Sstevel@tonic-gate return( NULLBER ); 560Sstevel@tonic-gate } 570Sstevel@tonic-gate 580Sstevel@tonic-gate if ( ber_printf( ber, "{it{s{so}}", ++ld->ld_msgid, LDAP_REQ_COMPARE, 590Sstevel@tonic-gate dn, attr, bvalue->bv_val, bvalue->bv_len ) == -1 ) { 600Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 610Sstevel@tonic-gate ber_free( ber, 1 ); 620Sstevel@tonic-gate return( NULLBER ); 630Sstevel@tonic-gate } 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* LDAPv3 */ 660Sstevel@tonic-gate /* Code controls if any */ 670Sstevel@tonic-gate if (serverctrls && serverctrls[0]) { 680Sstevel@tonic-gate if (ldap_controls_code(ber, serverctrls) != LDAP_SUCCESS){ 690Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 700Sstevel@tonic-gate return( NULLBER ); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate } else if (ld->ld_srvctrls && ld->ld_srvctrls[0]) { 730Sstevel@tonic-gate /* Otherwise, is there any global server ctrls ? */ 740Sstevel@tonic-gate if (ldap_controls_code(ber, ld->ld_srvctrls) != LDAP_SUCCESS){ 750Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 760Sstevel@tonic-gate return( NULLBER ); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate } 790Sstevel@tonic-gate if (ber_printf(ber, "}") == -1) { 800Sstevel@tonic-gate ld->ld_errno = LDAP_ENCODING_ERROR; 810Sstevel@tonic-gate ber_free(ber, 1); 820Sstevel@tonic-gate return (NULLBER); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate return (ber); 860Sstevel@tonic-gate } 870Sstevel@tonic-gate 880Sstevel@tonic-gate /* 890Sstevel@tonic-gate * ldap_compare - perform an ldap (and X.500) compare operation. The dn 900Sstevel@tonic-gate * of the entry to compare to and the attribute and value to compare (in 910Sstevel@tonic-gate * attr and value) are supplied. The msgid of the response is returned. 920Sstevel@tonic-gate * 930Sstevel@tonic-gate * Example: 940Sstevel@tonic-gate * ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" ) 950Sstevel@tonic-gate */ 960Sstevel@tonic-gate int 970Sstevel@tonic-gate ldap_compare( LDAP *ld, char *dn, char *attr, char *value ) 980Sstevel@tonic-gate { 990Sstevel@tonic-gate BerElement *ber; 1000Sstevel@tonic-gate struct berval bv; 1010Sstevel@tonic-gate int rv; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /* The compare request looks like this: 1040Sstevel@tonic-gate * CompareRequest ::= SEQUENCE { 1050Sstevel@tonic-gate * entry DistinguishedName, 1060Sstevel@tonic-gate * ava SEQUENCE { 1070Sstevel@tonic-gate * type AttributeType, 1080Sstevel@tonic-gate * value AttributeValue 1090Sstevel@tonic-gate * } 1100Sstevel@tonic-gate * } 1110Sstevel@tonic-gate * and must be wrapped in an LDAPMessage. 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate #ifdef _REENTRANT 1150Sstevel@tonic-gate LOCK_LDAP(ld); 1160Sstevel@tonic-gate #endif 1170Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 ); 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate bv.bv_val = value; 1200Sstevel@tonic-gate bv.bv_len = strlen(value); 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if ((ber = ldap_build_compare_req(ld, dn, attr, &bv, NULL)) == NULLBER) { 1230Sstevel@tonic-gate #ifdef _REENTRANT 1240Sstevel@tonic-gate UNLOCK_LDAP(ld); 1250Sstevel@tonic-gate #endif 1260Sstevel@tonic-gate return (-1); 1270Sstevel@tonic-gate } 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate #ifndef NO_CACHE 1300Sstevel@tonic-gate if ( ld->ld_cache != NULL ) { 1310Sstevel@tonic-gate if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) { 1320Sstevel@tonic-gate ber_free( ber, 1 ); 1330Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; 1340Sstevel@tonic-gate #ifdef _REENTRANT 1350Sstevel@tonic-gate UNLOCK_LDAP(ld); 1360Sstevel@tonic-gate #endif 1370Sstevel@tonic-gate return( ld->ld_msgid ); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate add_request_to_cache( ld, LDAP_REQ_COMPARE, ber ); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate #endif /* NO_CACHE */ 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* send the message */ 1440Sstevel@tonic-gate rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber ); 1450Sstevel@tonic-gate #ifdef _REENTRANT 1460Sstevel@tonic-gate UNLOCK_LDAP(ld); 1470Sstevel@tonic-gate #endif 1480Sstevel@tonic-gate return (rv); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate int 1520Sstevel@tonic-gate ldap_compare_s( LDAP *ld, char *dn, char *attr, char *value ) 1530Sstevel@tonic-gate { 1540Sstevel@tonic-gate int msgid; 1550Sstevel@tonic-gate LDAPMessage *res; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if ( (msgid = ldap_compare( ld, dn, attr, value )) == -1 ) 1580Sstevel@tonic-gate return( ld->ld_errno ); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) 1610Sstevel@tonic-gate return( ld->ld_errno ); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate return( ldap_result2error( ld, res, 1 ) ); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* LDAPv3 API extensions */ 1670Sstevel@tonic-gate int ldap_compare_ext(LDAP *ld, char *dn, char *attr, struct berval *bvalue, 1680Sstevel@tonic-gate LDAPControl ** serverctrls, LDAPControl **clientctrls, int *msgidp) 1690Sstevel@tonic-gate { 1700Sstevel@tonic-gate BerElement *ber; 1710Sstevel@tonic-gate struct berval bv; 1720Sstevel@tonic-gate int rv; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* The compare request looks like this: 1750Sstevel@tonic-gate * CompareRequest ::= SEQUENCE { 1760Sstevel@tonic-gate * entry DistinguishedName, 1770Sstevel@tonic-gate * ava SEQUENCE { 1780Sstevel@tonic-gate * type AttributeType, 1790Sstevel@tonic-gate * value AttributeValue 1800Sstevel@tonic-gate * } 1810Sstevel@tonic-gate * } 1820Sstevel@tonic-gate * and must be wrapped in an LDAPMessage. 1830Sstevel@tonic-gate */ 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate #ifdef _REENTRANT 1860Sstevel@tonic-gate LOCK_LDAP(ld); 1870Sstevel@tonic-gate #endif 1880Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 128, "ldap_compare\n"), 0, 0, 0 ); 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if ((ber = ldap_build_compare_req(ld, dn, attr, bvalue, NULL)) == NULLBER) { 1910Sstevel@tonic-gate rv = ld->ld_errno; 1920Sstevel@tonic-gate if (rv == LDAP_SUCCESS) 1930Sstevel@tonic-gate rv = LDAP_OTHER; 1940Sstevel@tonic-gate #ifdef _REENTRANT 1950Sstevel@tonic-gate UNLOCK_LDAP(ld); 1960Sstevel@tonic-gate #endif 1970Sstevel@tonic-gate return (rv); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate #ifndef NO_CACHE 2010Sstevel@tonic-gate if ( ld->ld_cache != NULL ) { 2020Sstevel@tonic-gate if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) { 2030Sstevel@tonic-gate ber_free( ber, 1 ); 2040Sstevel@tonic-gate ld->ld_errno = LDAP_SUCCESS; 2050Sstevel@tonic-gate *msgidp = ld->ld_msgid; 2060Sstevel@tonic-gate #ifdef _REENTRANT 2070Sstevel@tonic-gate UNLOCK_LDAP(ld); 2080Sstevel@tonic-gate #endif 2090Sstevel@tonic-gate return( LDAP_SUCCESS ); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate add_request_to_cache( ld, LDAP_REQ_COMPARE, ber ); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate #endif /* NO_CACHE */ 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* send the message */ 2160Sstevel@tonic-gate rv = send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber ); 2170Sstevel@tonic-gate if (rv == -1) { 2180Sstevel@tonic-gate rv = ld->ld_errno; 2190Sstevel@tonic-gate if (rv == LDAP_SUCCESS){ 2200Sstevel@tonic-gate rv = LDAP_OTHER; 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate #ifdef _REENTRANT 2230Sstevel@tonic-gate UNLOCK_LDAP(ld); 2240Sstevel@tonic-gate #endif 2250Sstevel@tonic-gate return (rv); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate *msgidp = rv; 2290Sstevel@tonic-gate #ifdef _REENTRANT 2300Sstevel@tonic-gate UNLOCK_LDAP(ld); 2310Sstevel@tonic-gate #endif 2320Sstevel@tonic-gate return (LDAP_SUCCESS); 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, struct berval *bvalue, 2360Sstevel@tonic-gate LDAPControl ** serverctrls, LDAPControl **clientctrls) 2370Sstevel@tonic-gate { 2380Sstevel@tonic-gate int msgid, retcode = LDAP_SUCCESS; 2390Sstevel@tonic-gate LDAPMessage *res; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate if ( (retcode = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) 2420Sstevel@tonic-gate return( retcode ); 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) 2450Sstevel@tonic-gate return( ld->ld_errno ); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate #ifdef _REENTRANT 2480Sstevel@tonic-gate LOCK_LDAP(ld); 2490Sstevel@tonic-gate #endif 2500Sstevel@tonic-gate retcode = ldap_parse_result( ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error, 2510Sstevel@tonic-gate &ld->ld_referrals, &ld->ld_ret_ctrls, 1); 2520Sstevel@tonic-gate if (retcode == LDAP_SUCCESS) 2530Sstevel@tonic-gate retcode = ld->ld_errno; 2540Sstevel@tonic-gate #ifdef _REENTRANT 2550Sstevel@tonic-gate UNLOCK_LDAP(ld); 2560Sstevel@tonic-gate #endif 2570Sstevel@tonic-gate return (retcode); 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 260