1 /* vc.c - LDAP Verify Credentials extop (no spec yet) */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2010 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was initially developed by Pierangelo Masarati for inclusion
18 * in OpenLDAP Software.
29 #include "ac/string.h"
31 typedef struct ConnExtraAuthzID {
36 static int authzid_cid;
37 static slap_overinst authzid;
39 static ConnExtraAuthzID *
40 authzid_extra_find( Connection *c )
44 LDAP_SLIST_FOREACH( cex, &c->c_extra, ce_next ) {
45 if ( cex->ce_key == (void *)&authzid_cid )
49 return (ConnExtraAuthzID *)cex;
52 static ConnExtraAuthzID *
53 authzid_extra_insert( Connection *c )
55 ConnExtraAuthzID *cex;
57 cex = SLAP_CALLOC( 1, sizeof( ConnExtraAuthzID ) );
58 cex->ce.ce_key = (void *)&authzid_cid;
60 LDAP_SLIST_INSERT_HEAD( &c->c_extra, &cex->ce, ce_next );
66 authzid_extra_remove( Connection *c )
71 cex = (ConnExtra *)authzid_extra_find( c );
74 LDAP_SLIST_REMOVE( &c->c_extra, cex, ConnExtra, ce_next );
86 ConnExtraAuthzID *cex;
88 struct berval edn = BER_BVNULL;
92 assert( rs->sr_tag = LDAP_RES_BIND );
94 cex = authzid_extra_find( op->o_conn );
95 if ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ) {
97 cex = authzid_extra_insert( op->o_conn );
98 cex->authzid_flag = op->o_ctrlflag[ authzid_cid ];
101 return SLAP_CB_CONTINUE;
106 authzid_extra_remove( op->o_conn );
109 if ( rs->sr_err != LDAP_SUCCESS ) {
110 return SLAP_CB_CONTINUE;
113 if ( !BER_BVISEMPTY( &op->orb_edn ) ) {
115 } else if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
116 edn = op->o_conn->c_dn;
119 if ( !BER_BVISEMPTY( &edn ) ) {
120 len = STRLENOF("dn:") + edn.bv_len;
123 /* save original controls in sc_private;
124 * will be restored by sc_cleanup
126 if ( rs->sr_ctrls != NULL ) {
127 op->o_callback->sc_private = rs->sr_ctrls;
128 for ( ; rs->sr_ctrls[n] != NULL; n++ )
132 ctrls = op->o_tmpalloc( sizeof( LDAPControl * )*( n + 2 ), op->o_tmpmemctx );
134 if ( rs->sr_ctrls ) {
135 for ( ; rs->sr_ctrls[n] != NULL; n++ ) {
136 ctrls[n] = rs->sr_ctrls[n];
140 /* anonymous: "", otherwise "dn:<dn>" */
141 ctrls[n] = op->o_tmpalloc( sizeof( LDAPControl ) + len + 1, op->o_tmpmemctx );
142 ctrls[n]->ldctl_oid = LDAP_CONTROL_AUTHZID_RESPONSE;
143 ctrls[n]->ldctl_iscritical = 0;
144 ctrls[n]->ldctl_value.bv_len = len;
145 ctrls[n]->ldctl_value.bv_val = (char *)&ctrls[n][1];
149 ptr = lutil_strcopy( ctrls[n]->ldctl_value.bv_val, "dn:" );
150 ptr = lutil_strncopy( ptr, edn.bv_val, edn.bv_len );
152 ctrls[n]->ldctl_value.bv_val[len] = '\0';
155 rs->sr_ctrls = ctrls;
157 return SLAP_CB_CONTINUE;
165 if ( rs->sr_ctrls ) {
168 /* if ours, cleanup */
169 ctrl = ldap_control_find( LDAP_CONTROL_AUTHZID_RESPONSE, rs->sr_ctrls, NULL );
171 op->o_tmpfree( ctrl, op->o_tmpmemctx );
172 op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
175 if ( op->o_callback->sc_private != NULL ) {
176 rs->sr_ctrls = (LDAPControl **)op->o_callback->sc_private;
177 op->o_callback->sc_private = NULL;
181 op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
182 op->o_callback = NULL;
184 return SLAP_CB_CONTINUE;
194 if ( op->o_ctrlflag[ authzid_cid ] <= SLAP_CONTROL_IGNORED ) {
195 ConnExtraAuthzID *cex = authzid_extra_find( op->o_conn );
197 op->o_ctrlflag[ authzid_cid ] = cex->authzid_flag;
201 if ( op->o_ctrlflag[ authzid_cid ] > SLAP_CONTROL_IGNORED ) {
203 op->o_callback = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx );
204 op->o_callback->sc_response = authzid_response;
205 op->o_callback->sc_cleanup = authzid_cleanup;
206 op->o_callback->sc_private = NULL;
207 op->o_callback->sc_next = sc;
210 return SLAP_CB_CONTINUE;
219 if ( op->o_ctrlflag[ authzid_cid ] != SLAP_CONTROL_NONE ) {
220 rs->sr_text = "authzid control specified multiple times";
221 return LDAP_PROTOCOL_ERROR;
224 if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
225 rs->sr_text = "authzid control value not absent";
226 return LDAP_PROTOCOL_ERROR;
229 /* drop ongoing requests */
230 (void)authzid_extra_remove( op->o_conn );
232 op->o_ctrlflag[ authzid_cid ] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL;
237 static int authzid_cnt;
240 authzid_db_init( BackendDB *be, ConfigReply *cr)
242 if ( authzid_cnt++ == 0 ) {
245 rc = register_supported_control( LDAP_CONTROL_AUTHZID_REQUEST,
246 SLAP_CTRL_GLOBAL|SLAP_CTRL_BIND|SLAP_CTRL_HIDE, NULL,
247 parse_authzid_ctrl, &authzid_cid );
248 if ( rc != LDAP_SUCCESS ) {
249 Debug( LDAP_DEBUG_ANY,
250 "authzid_initialize: Failed to register control '%s' (%d)\n",
251 LDAP_CONTROL_AUTHZID_REQUEST, rc, 0 );
260 authzid_db_destroy( BackendDB *be, ConfigReply *cr )
262 assert( authzid_cnt > 0 );
264 #ifdef SLAP_CONFIG_DELETE
265 overlay_unregister_control( be, LDAP_CONTROL_AUTHZID_REQUEST );
266 #endif /* SLAP_CONFIG_DELETE */
268 if ( --authzid_cnt == 0 ) {
269 unregister_supported_control( LDAP_CONTROL_AUTHZID_REQUEST );
276 authzid_initialize( void )
278 authzid.on_bi.bi_type = "authzid";
280 authzid.on_bi.bi_db_init = authzid_db_init;
281 authzid.on_bi.bi_db_destroy = authzid_db_destroy;
282 authzid.on_bi.bi_op_bind = authzid_op_bind;
284 return overlay_register( &authzid );
288 init_module( int argc, char *argv[] )
290 return authzid_initialize();