1/*	$NetBSD: compare.c,v 1.3 2021/08/14 16:14:55 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2021 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17/* Portions Copyright (c) 1990 Regents of the University of Michigan.
18 * All rights reserved.
19 */
20
21#include <sys/cdefs.h>
22__RCSID("$NetBSD: compare.c,v 1.3 2021/08/14 16:14:55 christos Exp $");
23
24#include "portable.h"
25
26#include <stdio.h>
27
28#include <ac/socket.h>
29#include <ac/string.h>
30#include <ac/time.h>
31
32#include "ldap-int.h"
33#include "ldap_log.h"
34
35/* The compare request looks like this:
36 *	CompareRequest ::= SEQUENCE {
37 *		entry	DistinguishedName,
38 *		ava	SEQUENCE {
39 *			type	AttributeType,
40 *			value	AttributeValue
41 *		}
42 *	}
43 */
44
45BerElement *
46ldap_build_compare_req(
47	LDAP *ld,
48	LDAP_CONST char *dn,
49	LDAP_CONST char *attr,
50	struct berval *bvalue,
51	LDAPControl **sctrls,
52	LDAPControl **cctrls,
53	int	*msgidp )
54{
55	BerElement	*ber;
56	int rc;
57
58	/* create a message to send */
59	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
60		return( NULL );
61	}
62
63	LDAP_NEXT_MSGID(ld, *msgidp);
64	rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */
65		*msgidp,
66		LDAP_REQ_COMPARE, dn, attr, bvalue );
67	if ( rc == -1 )
68	{
69		ld->ld_errno = LDAP_ENCODING_ERROR;
70		ber_free( ber, 1 );
71		return( NULL );
72	}
73
74	/* Put Server Controls */
75	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
76		ber_free( ber, 1 );
77		return( NULL );
78	}
79
80	if( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
81		ld->ld_errno = LDAP_ENCODING_ERROR;
82		ber_free( ber, 1 );
83		return( NULL );
84	}
85
86	return( ber );
87}
88
89/*
90 * ldap_compare_ext - perform an ldap extended compare operation.  The dn
91 * of the entry to compare to and the attribute and value to compare (in
92 * attr and value) are supplied.  The msgid of the response is returned.
93 *
94 * Example:
95 *	struct berval bvalue = { "secret", sizeof("secret")-1 };
96 *	rc = ldap_compare( ld, "c=us@cn=bob",
97 *		"userPassword", &bvalue,
98 *		sctrl, cctrl, &msgid )
99 */
100int
101ldap_compare_ext(
102	LDAP *ld,
103	LDAP_CONST char *dn,
104	LDAP_CONST char *attr,
105	struct berval *bvalue,
106	LDAPControl **sctrls,
107	LDAPControl **cctrls,
108	int	*msgidp )
109{
110	int rc;
111	BerElement	*ber;
112	ber_int_t	id;
113
114	Debug0( LDAP_DEBUG_TRACE, "ldap_compare\n" );
115
116	assert( ld != NULL );
117	assert( LDAP_VALID( ld ) );
118	assert( dn != NULL );
119	assert( attr != NULL );
120	assert( msgidp != NULL );
121
122	/* check client controls */
123	rc = ldap_int_client_controls( ld, cctrls );
124	if( rc != LDAP_SUCCESS ) return rc;
125
126	ber = ldap_build_compare_req(
127		ld, dn, attr, bvalue, sctrls, cctrls, &id );
128	if( !ber )
129		return ld->ld_errno;
130
131	/* send the message */
132	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber, id );
133	return ( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
134}
135
136/*
137 * ldap_compare_ext - perform an ldap extended compare operation.  The dn
138 * of the entry to compare to and the attribute and value to compare (in
139 * attr and value) are supplied.  The msgid of the response is returned.
140 *
141 * Example:
142 *	msgid = ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" )
143 */
144int
145ldap_compare(
146	LDAP *ld,
147	LDAP_CONST char *dn,
148	LDAP_CONST char *attr,
149	LDAP_CONST char *value )
150{
151	int msgid;
152	struct berval bvalue;
153
154	assert( value != NULL );
155
156	bvalue.bv_val = (char *) value;
157	bvalue.bv_len = (value == NULL) ? 0 : strlen( value );
158
159	return ldap_compare_ext( ld, dn, attr, &bvalue, NULL, NULL, &msgid ) == LDAP_SUCCESS
160		? msgid : -1;
161}
162
163int
164ldap_compare_ext_s(
165	LDAP *ld,
166	LDAP_CONST char *dn,
167	LDAP_CONST char *attr,
168	struct berval *bvalue,
169	LDAPControl **sctrl,
170	LDAPControl **cctrl )
171{
172	int		rc;
173	int		msgid;
174	LDAPMessage	*res;
175
176	rc = ldap_compare_ext( ld, dn, attr, bvalue, sctrl, cctrl, &msgid );
177
178	if (  rc != LDAP_SUCCESS )
179		return( rc );
180
181	if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res )
182		return( ld->ld_errno );
183
184	return( ldap_result2error( ld, res, 1 ) );
185}
186
187int
188ldap_compare_s(
189	LDAP *ld,
190	LDAP_CONST char *dn,
191	LDAP_CONST char *attr,
192	LDAP_CONST char *value )
193{
194	struct berval bvalue;
195
196	assert( value != NULL );
197
198	bvalue.bv_val = (char *) value;
199	bvalue.bv_len = (value == NULL) ? 0 : strlen( value );
200
201	return ldap_compare_ext_s( ld, dn, attr, &bvalue, NULL, NULL );
202}
203