1*549b59edSchristos /* $NetBSD: vc.c,v 1.2 2021/08/14 16:14:54 christos Exp $ */
2e670fd5cSchristos
3e670fd5cSchristos /* vc.c - LDAP Verify Credentials extop (no spec yet) */
4e670fd5cSchristos /* $OpenLDAP$ */
5e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6e670fd5cSchristos *
7e670fd5cSchristos * Copyright 2010-2021 The OpenLDAP Foundation.
8e670fd5cSchristos * All rights reserved.
9e670fd5cSchristos *
10e670fd5cSchristos * Redistribution and use in source and binary forms, with or without
11e670fd5cSchristos * modification, are permitted only as authorized by the OpenLDAP
12e670fd5cSchristos * Public License.
13e670fd5cSchristos *
14e670fd5cSchristos * A copy of this license is available in the file LICENSE in the
15e670fd5cSchristos * top-level directory of the distribution or, alternatively, at
16e670fd5cSchristos * <http://www.OpenLDAP.org/license.html>.
17e670fd5cSchristos */
18e670fd5cSchristos /* ACKNOWLEDGEMENTS:
19e670fd5cSchristos * This work was initially developed by Pierangelo Masarati for inclusion
20e670fd5cSchristos * in OpenLDAP Software.
21e670fd5cSchristos */
22e670fd5cSchristos
23e670fd5cSchristos /*
24e670fd5cSchristos * LDAP Verify Credentials: suggested by Kurt Zeilenga
25e670fd5cSchristos * no spec yet
26e670fd5cSchristos */
27e670fd5cSchristos
28e670fd5cSchristos #include <sys/cdefs.h>
29*549b59edSchristos __RCSID("$NetBSD: vc.c,v 1.2 2021/08/14 16:14:54 christos Exp $");
30e670fd5cSchristos
31e670fd5cSchristos #include "portable.h"
32e670fd5cSchristos
33e670fd5cSchristos #include "slap.h"
34e670fd5cSchristos #include "ac/string.h"
35e670fd5cSchristos
36e670fd5cSchristos typedef struct vc_conn_t {
37e670fd5cSchristos struct vc_conn_t *conn;
38e670fd5cSchristos Connection connbuf;
39e670fd5cSchristos OperationBuffer opbuf;
40e670fd5cSchristos Operation *op;
41e670fd5cSchristos int refcnt;
42e670fd5cSchristos } vc_conn_t;
43e670fd5cSchristos
44e670fd5cSchristos static const struct berval vc_exop_oid_bv = BER_BVC(LDAP_EXOP_VERIFY_CREDENTIALS);
45e670fd5cSchristos static ldap_pvt_thread_mutex_t vc_mutex;
46e670fd5cSchristos static Avlnode *vc_tree;
47e670fd5cSchristos
48e670fd5cSchristos static int
vc_conn_cmp(const void * c1,const void * c2)49e670fd5cSchristos vc_conn_cmp( const void *c1, const void *c2 )
50e670fd5cSchristos {
51e670fd5cSchristos const vc_conn_t *vc1 = (const vc_conn_t *)c1;
52e670fd5cSchristos const vc_conn_t *vc2 = (const vc_conn_t *)c2;
53e670fd5cSchristos
54e670fd5cSchristos return SLAP_PTRCMP( vc1->conn, vc2->conn );
55e670fd5cSchristos }
56e670fd5cSchristos
57e670fd5cSchristos static int
vc_conn_dup(void * c1,void * c2)58e670fd5cSchristos vc_conn_dup( void *c1, void *c2 )
59e670fd5cSchristos {
60e670fd5cSchristos vc_conn_t *vc1 = (vc_conn_t *)c1;
61e670fd5cSchristos vc_conn_t *vc2 = (vc_conn_t *)c2;
62e670fd5cSchristos
63e670fd5cSchristos if ( vc1->conn == vc2->conn ) {
64e670fd5cSchristos return -1;
65e670fd5cSchristos }
66e670fd5cSchristos
67e670fd5cSchristos return 0;
68e670fd5cSchristos }
69e670fd5cSchristos
70e670fd5cSchristos static int
vc_create_response(void * conn,int resultCode,const char * diagnosticMessage,struct berval * servercred,struct berval * authzid,LDAPControl ** ctrls,struct berval ** val)71e670fd5cSchristos vc_create_response(
72e670fd5cSchristos void *conn,
73e670fd5cSchristos int resultCode,
74e670fd5cSchristos const char *diagnosticMessage,
75e670fd5cSchristos struct berval *servercred,
76e670fd5cSchristos struct berval *authzid,
77e670fd5cSchristos LDAPControl **ctrls,
78e670fd5cSchristos struct berval **val )
79e670fd5cSchristos {
80e670fd5cSchristos BerElementBuffer berbuf;
81e670fd5cSchristos BerElement *ber = (BerElement *)&berbuf;
82e670fd5cSchristos struct berval bv;
83e670fd5cSchristos int rc;
84e670fd5cSchristos
85e670fd5cSchristos assert( val != NULL );
86e670fd5cSchristos
87e670fd5cSchristos *val = NULL;
88e670fd5cSchristos
89e670fd5cSchristos ber_init2( ber, NULL, LBER_USE_DER );
90e670fd5cSchristos
91e670fd5cSchristos (void)ber_printf( ber, "{is" /*}*/ , resultCode, diagnosticMessage ? diagnosticMessage : "" );
92e670fd5cSchristos
93e670fd5cSchristos if ( conn ) {
94e670fd5cSchristos struct berval cookie;
95e670fd5cSchristos
96e670fd5cSchristos cookie.bv_len = sizeof( conn );
97e670fd5cSchristos cookie.bv_val = (char *)&conn;
98e670fd5cSchristos (void)ber_printf( ber, "tO", 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, &cookie );
99e670fd5cSchristos }
100e670fd5cSchristos
101e670fd5cSchristos if ( servercred ) {
102e670fd5cSchristos ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS, servercred );
103e670fd5cSchristos }
104e670fd5cSchristos
105e670fd5cSchristos #if 0
106e670fd5cSchristos if ( authzid ) {
107e670fd5cSchristos ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_AUTHZID, authzid );
108e670fd5cSchristos }
109e670fd5cSchristos #endif
110e670fd5cSchristos
111e670fd5cSchristos if ( ctrls ) {
112e670fd5cSchristos int c;
113e670fd5cSchristos
114e670fd5cSchristos rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS );
115e670fd5cSchristos if ( rc == -1 ) goto done;
116e670fd5cSchristos
117e670fd5cSchristos for ( c = 0; ctrls[c] != NULL; c++ ) {
118e670fd5cSchristos rc = ber_printf( ber, "{s" /*}*/, ctrls[c]->ldctl_oid );
119e670fd5cSchristos
120e670fd5cSchristos if ( ctrls[c]->ldctl_iscritical ) {
121e670fd5cSchristos rc = ber_printf( ber, "b", (ber_int_t)ctrls[c]->ldctl_iscritical ) ;
122e670fd5cSchristos if ( rc == -1 ) goto done;
123e670fd5cSchristos }
124e670fd5cSchristos
125e670fd5cSchristos if ( ctrls[c]->ldctl_value.bv_val != NULL ) {
126e670fd5cSchristos rc = ber_printf( ber, "O", &ctrls[c]->ldctl_value );
127e670fd5cSchristos if( rc == -1 ) goto done;
128e670fd5cSchristos }
129e670fd5cSchristos
130e670fd5cSchristos rc = ber_printf( ber, /*{*/"N}" );
131e670fd5cSchristos if ( rc == -1 ) goto done;
132e670fd5cSchristos }
133e670fd5cSchristos
134e670fd5cSchristos rc = ber_printf( ber, /*{*/"N}" );
135e670fd5cSchristos if ( rc == -1 ) goto done;
136e670fd5cSchristos }
137e670fd5cSchristos
138e670fd5cSchristos rc = ber_printf( ber, /*{*/ "}" );
139e670fd5cSchristos if ( rc == -1 ) goto done;
140e670fd5cSchristos
141e670fd5cSchristos rc = ber_flatten2( ber, &bv, 0 );
142e670fd5cSchristos if ( rc == 0 ) {
143e670fd5cSchristos *val = ber_bvdup( &bv );
144e670fd5cSchristos }
145e670fd5cSchristos
146e670fd5cSchristos done:;
147e670fd5cSchristos ber_free_buf( ber );
148e670fd5cSchristos
149e670fd5cSchristos return rc;
150e670fd5cSchristos }
151e670fd5cSchristos
152e670fd5cSchristos typedef struct vc_cb_t {
153e670fd5cSchristos struct berval sasldata;
154e670fd5cSchristos LDAPControl **ctrls;
155e670fd5cSchristos } vc_cb_t;
156e670fd5cSchristos
157e670fd5cSchristos static int
vc_cb(Operation * op,SlapReply * rs)158e670fd5cSchristos vc_cb(
159e670fd5cSchristos Operation *op,
160e670fd5cSchristos SlapReply *rs )
161e670fd5cSchristos {
162e670fd5cSchristos vc_cb_t *vc = (vc_cb_t *)op->o_callback->sc_private;
163e670fd5cSchristos
164e670fd5cSchristos if ( rs->sr_tag == LDAP_RES_BIND ) {
165e670fd5cSchristos if ( rs->sr_sasldata != NULL ) {
166e670fd5cSchristos ber_dupbv( &vc->sasldata, rs->sr_sasldata );
167e670fd5cSchristos }
168e670fd5cSchristos
169e670fd5cSchristos if ( rs->sr_ctrls != NULL ) {
170e670fd5cSchristos vc->ctrls = ldap_controls_dup( rs->sr_ctrls );
171e670fd5cSchristos }
172e670fd5cSchristos }
173e670fd5cSchristos
174e670fd5cSchristos return 0;
175e670fd5cSchristos }
176e670fd5cSchristos
177e670fd5cSchristos static int
vc_exop(Operation * op,SlapReply * rs)178e670fd5cSchristos vc_exop(
179e670fd5cSchristos Operation *op,
180e670fd5cSchristos SlapReply *rs )
181e670fd5cSchristos {
182e670fd5cSchristos int rc = LDAP_SUCCESS;
183e670fd5cSchristos ber_tag_t tag;
184e670fd5cSchristos ber_len_t len = -1;
185e670fd5cSchristos BerElementBuffer berbuf;
186e670fd5cSchristos BerElement *ber = (BerElement *)&berbuf;
187e670fd5cSchristos struct berval reqdata = BER_BVNULL;
188e670fd5cSchristos
189e670fd5cSchristos struct berval cookie = BER_BVNULL;
190e670fd5cSchristos struct berval bdn = BER_BVNULL;
191e670fd5cSchristos ber_tag_t authtag;
192e670fd5cSchristos struct berval cred = BER_BVNULL;
193e670fd5cSchristos struct berval ndn = BER_BVNULL;
194e670fd5cSchristos struct berval mechanism = BER_BVNULL;
195e670fd5cSchristos
196e670fd5cSchristos vc_conn_t *conn = NULL;
197e670fd5cSchristos vc_cb_t vc = { 0 };
198e670fd5cSchristos slap_callback sc = { 0 };
199e670fd5cSchristos SlapReply rs2 = { 0 };
200e670fd5cSchristos
201e670fd5cSchristos if ( op->ore_reqdata == NULL || op->ore_reqdata->bv_len == 0 ) {
202e670fd5cSchristos rs->sr_text = "empty request data field in VerifyCredentials exop";
203e670fd5cSchristos return LDAP_PROTOCOL_ERROR;
204e670fd5cSchristos }
205e670fd5cSchristos
206e670fd5cSchristos /* optimistic */
207e670fd5cSchristos rs->sr_err = LDAP_SUCCESS;
208e670fd5cSchristos
209e670fd5cSchristos ber_dupbv_x( &reqdata, op->ore_reqdata, op->o_tmpmemctx );
210e670fd5cSchristos
211e670fd5cSchristos /* ber_init2 uses reqdata directly, doesn't allocate new buffers */
212e670fd5cSchristos ber_init2( ber, &reqdata, 0 );
213e670fd5cSchristos
214e670fd5cSchristos tag = ber_scanf( ber, "{" /*}*/ );
215e670fd5cSchristos if ( tag != LBER_SEQUENCE ) {
216e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
217e670fd5cSchristos goto done;
218e670fd5cSchristos }
219e670fd5cSchristos
220e670fd5cSchristos tag = ber_peek_tag( ber, &len );
221e670fd5cSchristos if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ) {
222e670fd5cSchristos /*
223e670fd5cSchristos * cookie: the pointer to the connection
224e670fd5cSchristos * of this operation
225e670fd5cSchristos */
226e670fd5cSchristos
227e670fd5cSchristos ber_scanf( ber, "m", &cookie );
228e670fd5cSchristos if ( cookie.bv_len != sizeof(Connection *) ) {
229e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
230e670fd5cSchristos goto done;
231e670fd5cSchristos }
232e670fd5cSchristos }
233e670fd5cSchristos
234e670fd5cSchristos /* DN, authtag */
235e670fd5cSchristos tag = ber_scanf( ber, "mt", &bdn, &authtag );
236e670fd5cSchristos if ( tag == LBER_ERROR ) {
237e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
238e670fd5cSchristos goto done;
239e670fd5cSchristos }
240e670fd5cSchristos
241e670fd5cSchristos rc = dnNormalize( 0, NULL, NULL, &bdn, &ndn, op->o_tmpmemctx );
242e670fd5cSchristos if ( rc != LDAP_SUCCESS ) {
243e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
244e670fd5cSchristos goto done;
245e670fd5cSchristos }
246e670fd5cSchristos
247e670fd5cSchristos switch ( authtag ) {
248e670fd5cSchristos case LDAP_AUTH_SIMPLE:
249e670fd5cSchristos /* cookie only makes sense for SASL bind (so far) */
250e670fd5cSchristos if ( !BER_BVISNULL( &cookie ) ) {
251e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
252e670fd5cSchristos goto done;
253e670fd5cSchristos }
254e670fd5cSchristos
255e670fd5cSchristos tag = ber_scanf( ber, "m", &cred );
256e670fd5cSchristos if ( tag == LBER_ERROR ) {
257e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
258e670fd5cSchristos goto done;
259e670fd5cSchristos }
260e670fd5cSchristos break;
261e670fd5cSchristos
262e670fd5cSchristos case LDAP_AUTH_SASL:
263e670fd5cSchristos tag = ber_scanf( ber, "{m" /*}*/ , &mechanism );
264e670fd5cSchristos if ( tag == LBER_ERROR ||
265e670fd5cSchristos BER_BVISNULL( &mechanism ) || BER_BVISEMPTY( &mechanism ) )
266e670fd5cSchristos {
267e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
268e670fd5cSchristos goto done;
269e670fd5cSchristos }
270e670fd5cSchristos
271e670fd5cSchristos tag = ber_peek_tag( ber, &len );
272e670fd5cSchristos if ( tag == LBER_OCTETSTRING ) {
273e670fd5cSchristos ber_scanf( ber, "m", &cred );
274e670fd5cSchristos }
275e670fd5cSchristos
276e670fd5cSchristos tag = ber_scanf( ber, /*{*/ "}" );
277e670fd5cSchristos break;
278e670fd5cSchristos
279e670fd5cSchristos default:
280e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
281e670fd5cSchristos goto done;
282e670fd5cSchristos }
283e670fd5cSchristos
284e670fd5cSchristos if ( !BER_BVISNULL( &cookie ) ) {
285e670fd5cSchristos vc_conn_t tmp = { 0 };
286e670fd5cSchristos
287e670fd5cSchristos AC_MEMCPY( (char *)&tmp.conn, (const char *)cookie.bv_val, cookie.bv_len );
288e670fd5cSchristos ldap_pvt_thread_mutex_lock( &vc_mutex );
289e670fd5cSchristos conn = (vc_conn_t *)ldap_avl_find( vc_tree, (caddr_t)&tmp, vc_conn_cmp );
290e670fd5cSchristos if ( conn == NULL || ( conn != NULL && conn->refcnt != 0 ) ) {
291e670fd5cSchristos conn = NULL;
292e670fd5cSchristos ldap_pvt_thread_mutex_unlock( &vc_mutex );
293e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
294e670fd5cSchristos goto done;
295e670fd5cSchristos }
296e670fd5cSchristos conn->refcnt++;
297e670fd5cSchristos ldap_pvt_thread_mutex_unlock( &vc_mutex );
298e670fd5cSchristos
299e670fd5cSchristos } else {
300e670fd5cSchristos void *thrctx;
301e670fd5cSchristos
302e670fd5cSchristos conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) );
303e670fd5cSchristos conn->refcnt = 1;
304e670fd5cSchristos
305e670fd5cSchristos thrctx = ldap_pvt_thread_pool_context();
306e670fd5cSchristos connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 );
307e670fd5cSchristos conn->op = &conn->opbuf.ob_op;
308e670fd5cSchristos snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ),
309e670fd5cSchristos "%s VERIFYCREDENTIALS", op->o_log_prefix );
310e670fd5cSchristos }
311e670fd5cSchristos
312e670fd5cSchristos conn->op->o_tag = LDAP_REQ_BIND;
313e670fd5cSchristos memset( &conn->op->oq_bind, 0, sizeof( conn->op->oq_bind ) );
314e670fd5cSchristos conn->op->o_req_dn = ndn;
315e670fd5cSchristos conn->op->o_req_ndn = ndn;
316e670fd5cSchristos conn->op->o_protocol = LDAP_VERSION3;
317e670fd5cSchristos conn->op->orb_method = authtag;
318e670fd5cSchristos conn->op->o_callback = ≻
319e670fd5cSchristos
320e670fd5cSchristos /* TODO: controls */
321e670fd5cSchristos tag = ber_peek_tag( ber, &len );
322e670fd5cSchristos if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ) {
323e670fd5cSchristos conn->op->o_ber = ber;
324e670fd5cSchristos rc = get_ctrls2( conn->op, &rs2, 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS );
325e670fd5cSchristos if ( rc != LDAP_SUCCESS ) {
326e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
327e670fd5cSchristos goto done;
328e670fd5cSchristos }
329e670fd5cSchristos }
330e670fd5cSchristos
331e670fd5cSchristos tag = ber_skip_tag( ber, &len );
332e670fd5cSchristos if ( len || tag != LBER_DEFAULT ) {
333e670fd5cSchristos rs->sr_err = LDAP_PROTOCOL_ERROR;
334e670fd5cSchristos goto done;
335e670fd5cSchristos }
336e670fd5cSchristos
337e670fd5cSchristos switch ( authtag ) {
338e670fd5cSchristos case LDAP_AUTH_SIMPLE:
339e670fd5cSchristos break;
340e670fd5cSchristos
341e670fd5cSchristos case LDAP_AUTH_SASL:
342e670fd5cSchristos conn->op->orb_mech = mechanism;
343e670fd5cSchristos break;
344e670fd5cSchristos }
345e670fd5cSchristos
346e670fd5cSchristos conn->op->orb_cred = cred;
347e670fd5cSchristos sc.sc_response = vc_cb;
348e670fd5cSchristos sc.sc_private = &vc;
349e670fd5cSchristos
350e670fd5cSchristos conn->op->o_bd = frontendDB;
351e670fd5cSchristos rs->sr_err = frontendDB->be_bind( conn->op, &rs2 );
352e670fd5cSchristos
353e670fd5cSchristos if ( conn->op->o_conn->c_sasl_bind_in_progress ) {
354e670fd5cSchristos rc = vc_create_response( conn, rs2.sr_err, rs2.sr_text,
355e670fd5cSchristos !BER_BVISEMPTY( &vc.sasldata ) ? &vc.sasldata : NULL,
356e670fd5cSchristos NULL,
357e670fd5cSchristos vc.ctrls, &rs->sr_rspdata );
358e670fd5cSchristos
359e670fd5cSchristos } else {
360e670fd5cSchristos rc = vc_create_response( NULL, rs2.sr_err, rs2.sr_text,
361e670fd5cSchristos NULL,
362e670fd5cSchristos &conn->op->o_conn->c_dn,
363e670fd5cSchristos vc.ctrls, &rs->sr_rspdata );
364e670fd5cSchristos }
365e670fd5cSchristos
366e670fd5cSchristos if ( rc != 0 ) {
367e670fd5cSchristos rs->sr_err = LDAP_OTHER;
368e670fd5cSchristos goto done;
369e670fd5cSchristos }
370e670fd5cSchristos
371e670fd5cSchristos if ( !BER_BVISNULL( &conn->op->o_conn->c_dn ) &&
372e670fd5cSchristos conn->op->o_conn->c_dn.bv_val != conn->op->o_conn->c_ndn.bv_val )
373e670fd5cSchristos ber_memfree( conn->op->o_conn->c_dn.bv_val );
374e670fd5cSchristos if ( !BER_BVISNULL( &conn->op->o_conn->c_ndn ) )
375e670fd5cSchristos ber_memfree( conn->op->o_conn->c_ndn.bv_val );
376e670fd5cSchristos
377e670fd5cSchristos done:;
378e670fd5cSchristos if ( conn ) {
379e670fd5cSchristos if ( conn->op->o_conn->c_sasl_bind_in_progress ) {
380e670fd5cSchristos if ( conn->conn == NULL ) {
381e670fd5cSchristos conn->conn = conn;
382e670fd5cSchristos conn->refcnt--;
383e670fd5cSchristos ldap_pvt_thread_mutex_lock( &vc_mutex );
384e670fd5cSchristos rc = ldap_avl_insert( &vc_tree, (caddr_t)conn,
385e670fd5cSchristos vc_conn_cmp, vc_conn_dup );
386e670fd5cSchristos ldap_pvt_thread_mutex_unlock( &vc_mutex );
387e670fd5cSchristos assert( rc == 0 );
388e670fd5cSchristos
389e670fd5cSchristos } else {
390e670fd5cSchristos ldap_pvt_thread_mutex_lock( &vc_mutex );
391e670fd5cSchristos conn->refcnt--;
392e670fd5cSchristos ldap_pvt_thread_mutex_unlock( &vc_mutex );
393e670fd5cSchristos }
394e670fd5cSchristos
395e670fd5cSchristos } else {
396e670fd5cSchristos if ( conn->conn != NULL ) {
397e670fd5cSchristos vc_conn_t *tmp;
398e670fd5cSchristos
399e670fd5cSchristos ldap_pvt_thread_mutex_lock( &vc_mutex );
400e670fd5cSchristos tmp = ldap_avl_delete( &vc_tree, (caddr_t)conn, vc_conn_cmp );
401e670fd5cSchristos ldap_pvt_thread_mutex_unlock( &vc_mutex );
402e670fd5cSchristos }
403e670fd5cSchristos SLAP_FREE( conn );
404e670fd5cSchristos }
405e670fd5cSchristos }
406e670fd5cSchristos
407e670fd5cSchristos if ( vc.ctrls ) {
408e670fd5cSchristos ldap_controls_free( vc.ctrls );
409e670fd5cSchristos vc.ctrls = NULL;
410e670fd5cSchristos }
411e670fd5cSchristos
412e670fd5cSchristos if ( !BER_BVISNULL( &ndn ) ) {
413e670fd5cSchristos op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
414e670fd5cSchristos BER_BVZERO( &ndn );
415e670fd5cSchristos }
416e670fd5cSchristos
417e670fd5cSchristos op->o_tmpfree( reqdata.bv_val, op->o_tmpmemctx );
418e670fd5cSchristos BER_BVZERO( &reqdata );
419e670fd5cSchristos
420e670fd5cSchristos return rs->sr_err;
421e670fd5cSchristos }
422e670fd5cSchristos
423e670fd5cSchristos static int
vc_initialize(void)424e670fd5cSchristos vc_initialize( void )
425e670fd5cSchristos {
426e670fd5cSchristos int rc;
427e670fd5cSchristos
428e670fd5cSchristos rc = load_extop2( (struct berval *)&vc_exop_oid_bv,
429e670fd5cSchristos SLAP_EXOP_HIDE, vc_exop, 0 );
430e670fd5cSchristos if ( rc != LDAP_SUCCESS ) {
431e670fd5cSchristos Debug( LDAP_DEBUG_ANY,
432e670fd5cSchristos "vc_initialize: unable to register VerifyCredentials exop: %d.\n",
433e670fd5cSchristos rc );
434e670fd5cSchristos }
435e670fd5cSchristos
436e670fd5cSchristos ldap_pvt_thread_mutex_init( &vc_mutex );
437e670fd5cSchristos
438e670fd5cSchristos return rc;
439e670fd5cSchristos }
440e670fd5cSchristos
441e670fd5cSchristos int
init_module(int argc,char * argv[])442e670fd5cSchristos init_module( int argc, char *argv[] )
443e670fd5cSchristos {
444e670fd5cSchristos return vc_initialize();
445e670fd5cSchristos }
446e670fd5cSchristos
447