Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
openldap
OpenLDAP
Commits
9813ce55
Commit
9813ce55
authored
Aug 26, 2010
by
Pierangelo Masarati
Browse files
add (partial) support for draft-ietf-ldapext-ldapv3-dupent-08.txt (expired)
parent
3e2ca2f8
Changes
2
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/dupent/Makefile
0 → 100644
View file @
9813ce55
# $OpenLDAP$
# This work is part of OpenLDAP Software <http://www.openldap.org/>.
#
# Copyright 1998-2010 The OpenLDAP Foundation.
# Copyright 2004 Howard Chu, Symas Corp. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted only as authorized by the OpenLDAP
# Public License.
#
# A copy of this license is available in the file LICENSE in the
# top-level directory of the distribution or, alternatively, at
# <http://www.OpenLDAP.org/license.html>.
LIBTOOL
=
../../../libtool
OPT
=
-DSLAPD_OVER_DUPENT
=
2
-g
-O2
#LIBTOOL=../../../../ldap-devel/libtool
#OPT=-DSLAPD_OVER_DUPENT=2 -g -O0
CC
=
gcc
LDAP_INC
=
-I
../../../include
-I
../../../servers/slapd
#LDAP_INC=-I../../../include -I../../../servers/slapd -I../../../../ldap-devel/include
INCS
=
$(LDAP_INC)
LDAP_LIB
=
-lldap_r
-llber
LIBS
=
$(LDAP_LIB)
prefix
=
/usr/local
exec_prefix
=
$(prefix)
ldap_subdir
=
/openldap
libdir
=
$(exec_prefix)
/lib
libexecdir
=
$(exec_prefix)
/libexec
moduledir
=
$(libexecdir)$(ldap_subdir)
all
:
dupent.la
dupent.lo
:
dupent.c
$(LIBTOOL)
--mode
=
compile
$(CC)
$(OPT)
$(DEFS)
$(INCS)
-c
$?
dupent.la
:
dupent.lo
$(LIBTOOL)
--mode
=
link
$(CC)
$(OPT)
-version-info
0:0:0
\
-rpath
$(moduledir)
-module
-o
$@
$?
$(LIBS)
clean
:
rm
-f
dupent.lo dupent.la
install
:
dupent.la
mkdir
-p
$(DESTDIR)$(moduledir)
$(LIBTOOL)
--mode
=
install cp
dupent.la
$(DESTDIR)$(moduledir)
contrib/slapd-modules/dupent/dupent.c
0 → 100644
View file @
9813ce55
/* dupent.c - LDAP Control for a Duplicate Entry Representation of Search Results */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2006-2010 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Pierangelo Masarati for inclusion
* in OpenLDAP Software.
*/
/*
* LDAP Control for a Duplicate Entry Representation of Search Results
* <draft-ietf-ldapext-ldapv3-dupent-08.txt> (EXPIRED)
* <http://tools.ietf.org/id/draft-ietf-ldapext-ldapv3-dupent-08.txt>
*/
#include
"portable.h"
/* define SLAPD_OVER_DUPENT=2 to build as run-time loadable module */
#ifdef SLAPD_OVER_DUPENT
/*
* The macros
*
* LDAP_CONTROL_DUPENT_REQUEST "2.16.840.1.113719.1.27.101.1"
* LDAP_CONTROL_DUPENT_RESPONSE "2.16.840.1.113719.1.27.101.2"
* LDAP_CONTROL_DUPENT_ENTRY "2.16.840.1.113719.1.27.101.3"
*
* are already defined in <ldap.h>
*/
/*
* support for no attrs and "*" in AttributeDescriptionList is missing
*/
#include
"slap.h"
#include
"ac/string.h"
#define o_dupent o_ctrlflag[dupent_cid]
#define o_ctrldupent o_controls[dupent_cid]
static
int
dupent_cid
;
static
slap_overinst
dupent
;
typedef
struct
dupent_t
{
AttributeName
*
ds_an
;
ber_len_t
ds_nattrs
;
slap_mask_t
ds_flags
;
ber_int_t
ds_paa
;
}
dupent_t
;
static
int
dupent_parseCtrl
(
Operation
*
op
,
SlapReply
*
rs
,
LDAPControl
*
ctrl
)
{
ber_tag_t
tag
;
BerElementBuffer
berbuf
;
BerElement
*
ber
=
(
BerElement
*
)
&
berbuf
;
ber_len_t
len
;
BerVarray
AttributeDescriptionList
=
NULL
;
ber_len_t
cnt
=
sizeof
(
struct
berval
);
ber_len_t
off
=
0
;
ber_int_t
PartialApplicationAllowed
=
1
;
dupent_t
*
ds
=
NULL
;
int
i
,
c
;
if
(
op
->
o_dupent
!=
SLAP_CONTROL_NONE
)
{
rs
->
sr_text
=
"Dupent control specified multiple times"
;
return
LDAP_PROTOCOL_ERROR
;
}
if
(
BER_BVISNULL
(
&
ctrl
->
ldctl_value
)
)
{
rs
->
sr_text
=
"Dupent control value is absent"
;
return
LDAP_PROTOCOL_ERROR
;
}
if
(
BER_BVISEMPTY
(
&
ctrl
->
ldctl_value
)
)
{
rs
->
sr_text
=
"Dupent control value is empty"
;
return
LDAP_PROTOCOL_ERROR
;
}
ber_init2
(
ber
,
&
ctrl
->
ldctl_value
,
0
);
/*
DuplicateEntryRequest ::= SEQUENCE {
AttributeDescriptionList, -- from [RFC2251]
PartialApplicationAllowed BOOLEAN DEFAULT TRUE }
AttributeDescriptionList ::= SEQUENCE OF
AttributeDescription
AttributeDescription ::= LDAPString
attributeDescription = AttributeType [ ";" <options> ]
*/
tag
=
ber_skip_tag
(
ber
,
&
len
);
if
(
tag
!=
LBER_SEQUENCE
)
return
LDAP_INVALID_SYNTAX
;
if
(
ber_scanf
(
ber
,
"{M}"
,
&
AttributeDescriptionList
,
&
cnt
,
off
)
==
LBER_ERROR
)
{
rs
->
sr_text
=
"Dupent control: dupentSpec decoding error"
;
rs
->
sr_err
=
LDAP_PROTOCOL_ERROR
;
goto
done
;
}
tag
=
ber_skip_tag
(
ber
,
&
len
);
if
(
tag
==
LBER_BOOLEAN
)
{
/* NOTE: PartialApplicationAllowed is ignored, since the control
* can always be honored
*/
if
(
ber_scanf
(
ber
,
"b"
,
&
PartialApplicationAllowed
)
==
LBER_ERROR
)
{
rs
->
sr_text
=
"Dupent control: dupentSpec decoding error"
;
rs
->
sr_err
=
LDAP_PROTOCOL_ERROR
;
goto
done
;
}
tag
=
ber_skip_tag
(
ber
,
&
len
);
}
if
(
len
||
tag
!=
LBER_DEFAULT
)
{
rs
->
sr_text
=
"Dupent control: dupentSpec decoding error"
;
rs
->
sr_err
=
LDAP_PROTOCOL_ERROR
;
goto
done
;
}
/* FIXME: temporary */
if
(
cnt
==
0
)
{
rs
->
sr_text
=
"Dupent control: no attrs not supported"
;
rs
->
sr_err
=
LDAP_UNAVAILABLE_CRITICAL_EXTENSION
;
goto
done
;
}
ds
=
(
dupent_t
*
)
op
->
o_tmpcalloc
(
1
,
sizeof
(
dupent_t
)
+
sizeof
(
AttributeName
)
*
(
cnt
+
1
),
op
->
o_tmpmemctx
);
ds
->
ds_an
=
(
AttributeName
*
)
&
ds
[
1
];
ds
->
ds_flags
=
0
;
ds
->
ds_paa
=
PartialApplicationAllowed
;
for
(
i
=
0
,
c
=
0
;
i
<
cnt
;
i
++
)
{
const
char
*
text
;
int
j
;
int
rc
;
AttributeDescription
*
ad
=
NULL
;
if
(
bvmatch
(
&
AttributeDescriptionList
[
i
],
slap_bv_all_user_attrs
)
)
{
if
(
ds
->
ds_flags
&
SLAP_USERATTRS_YES
)
{
rs
->
sr_text
=
"Dupent control: AttributeDescription decoding error"
;
rs
->
sr_err
=
LDAP_PROTOCOL_ERROR
;
goto
done
;
}
/* FIXME: temporary */
rs
->
sr_text
=
"Dupent control: all user attrs not supported"
;
rs
->
sr_err
=
LDAP_UNAVAILABLE_CRITICAL_EXTENSION
;
goto
done
;
ds
->
ds_flags
|=
SLAP_USERATTRS_YES
;
continue
;
}
rc
=
slap_bv2ad
(
&
AttributeDescriptionList
[
i
],
&
ad
,
&
text
);
if
(
rc
!=
LDAP_SUCCESS
)
{
#if 0
rs->sr_text = "Dupent control: AttributeDescription decoding error";
rs->sr_err = LDAP_PROTOCOL_ERROR;
goto done;
#endif
continue
;
}
ds
->
ds_an
[
c
].
an_desc
=
ad
;
ds
->
ds_an
[
c
].
an_name
=
ad
->
ad_cname
;
/* FIXME: not specified; we avoid it just in case */
for
(
j
=
0
;
j
<
c
;
j
++
)
{
if
(
ds
->
ds_an
[
c
].
an_desc
==
ds
->
ds_an
[
j
].
an_desc
)
{
rs
->
sr_text
=
"Dupent control: AttributeDescription must be unique within AttributeDescriptionList"
;
rs
->
sr_err
=
LDAP_PROTOCOL_ERROR
;
goto
done
;
}
}
c
++
;
}
ds
->
ds_nattrs
=
c
;
ber_memfree_x
(
AttributeDescriptionList
,
op
->
o_tmpmemctx
);
AttributeDescriptionList
=
NULL
;
op
->
o_ctrldupent
=
(
void
*
)
ds
;
op
->
o_dupent
=
ctrl
->
ldctl_iscritical
?
SLAP_CONTROL_CRITICAL
:
SLAP_CONTROL_NONCRITICAL
;
rs
->
sr_err
=
LDAP_SUCCESS
;
done:
;
if
(
rs
->
sr_err
!=
LDAP_SUCCESS
)
{
op
->
o_tmpfree
(
ds
,
op
->
o_tmpmemctx
);
}
if
(
AttributeDescriptionList
!=
NULL
)
{
ber_memfree_x
(
AttributeDescriptionList
,
op
->
o_tmpmemctx
);
}
return
rs
->
sr_err
;
}
typedef
struct
dupent_cb_t
{
slap_overinst
*
dc_on
;
dupent_t
*
dc_ds
;
int
dc_skip
;
}
dupent_cb_t
;
typedef
struct
valnum_t
{
Attribute
*
ap
;
Attribute
a
;
struct
berval
vals
[
2
];
struct
berval
nvals
[
2
];
int
cnt
;
}
valnum_t
;
static
int
dupent_response_done
(
Operation
*
op
,
SlapReply
*
rs
)
{
BerElementBuffer
berbuf
;
BerElement
*
ber
=
(
BerElement
*
)
&
berbuf
;
struct
berval
ctrlval
;
LDAPControl
*
ctrl
,
*
ctrlsp
[
2
];
ber_init2
(
ber
,
NULL
,
LBER_USE_DER
);
/*
DuplicateEntryResponseDone ::= SEQUENCE {
resultCode, -- From [RFC2251]
errorMessage [0] LDAPString OPTIONAL,
attribute [1] AttributeDescription OPTIONAL }
*/
ber_printf
(
ber
,
"{i}"
,
&
rs
->
sr_err
);
if
(
ber_flatten2
(
ber
,
&
ctrlval
,
0
)
==
-
1
)
{
ber_free_buf
(
ber
);
if
(
op
->
o_dupent
==
SLAP_CONTROL_CRITICAL
)
{
return
LDAP_CONSTRAINT_VIOLATION
;
}
return
SLAP_CB_CONTINUE
;
}
ctrl
=
op
->
o_tmpcalloc
(
1
,
sizeof
(
LDAPControl
)
+
ctrlval
.
bv_len
+
1
,
op
->
o_tmpmemctx
);
ctrl
->
ldctl_value
.
bv_val
=
(
char
*
)
&
ctrl
[
1
];
ctrl
->
ldctl_oid
=
LDAP_CONTROL_DUPENT_RESPONSE
;
ctrl
->
ldctl_iscritical
=
0
;
ctrl
->
ldctl_value
.
bv_len
=
ctrlval
.
bv_len
;
AC_MEMCPY
(
ctrl
->
ldctl_value
.
bv_val
,
ctrlval
.
bv_val
,
ctrlval
.
bv_len
);
ctrl
->
ldctl_value
.
bv_val
[
ctrl
->
ldctl_value
.
bv_len
]
=
'\0'
;
ber_free_buf
(
ber
);
ctrlsp
[
0
]
=
ctrl
;
ctrlsp
[
1
]
=
NULL
;
slap_add_ctrls
(
op
,
rs
,
ctrlsp
);
return
SLAP_CB_CONTINUE
;
}
static
int
dupent_response_entry_1level
(
Operation
*
op
,
SlapReply
*
rs
,
Entry
*
e
,
valnum_t
*
valnum
,
int
nattrs
,
int
level
)
{
int
i
,
rc
=
LDAP_SUCCESS
;
for
(
i
=
0
;
i
<
valnum
[
level
].
ap
->
a_numvals
;
i
++
)
{
LDAPControl
*
ctrl
=
NULL
,
*
ctrlsp
[
2
];
valnum
[
level
].
a
.
a_vals
[
0
]
=
valnum
[
level
].
ap
->
a_vals
[
i
];
if
(
valnum
[
level
].
ap
->
a_nvals
!=
valnum
[
level
].
ap
->
a_vals
)
{
valnum
[
level
].
a
.
a_nvals
[
0
]
=
valnum
[
level
].
ap
->
a_nvals
[
i
];
}
if
(
level
<
nattrs
-
1
)
{
rc
=
dupent_response_entry_1level
(
op
,
rs
,
e
,
valnum
,
nattrs
,
level
+
1
);
if
(
rc
!=
LDAP_SUCCESS
)
{
break
;
}
continue
;
}
/* NOTE: add the control all times, under the assumption
* send_search_entry() honors the REP_CTRLS_MUSTBEFREED
* set by slap_add_ctrls(); this is not true (ITS#6629)
*/
ctrl
=
op
->
o_tmpcalloc
(
1
,
sizeof
(
LDAPControl
),
op
->
o_tmpmemctx
);
ctrl
->
ldctl_oid
=
LDAP_CONTROL_DUPENT_ENTRY
;
ctrl
->
ldctl_iscritical
=
0
;
ctrlsp
[
0
]
=
ctrl
;
ctrlsp
[
1
]
=
NULL
;
slap_add_ctrls
(
op
,
rs
,
ctrlsp
);
/* do the real send */
rs
->
sr_entry
=
e
;
rc
=
send_search_entry
(
op
,
rs
);
if
(
rc
!=
LDAP_SUCCESS
)
{
break
;
}
}
return
rc
;
}
static
int
dupent_response_entry
(
Operation
*
op
,
SlapReply
*
rs
)
{
dupent_cb_t
*
dc
=
(
dupent_cb_t
*
)
op
->
o_callback
->
sc_private
;
int
nattrs
=
0
;
valnum_t
*
valnum
=
NULL
;
Attribute
**
app
,
*
ap_list
=
NULL
;
int
i
,
c
;
Entry
*
e
=
NULL
;
int
rc
;
assert
(
rs
->
sr_type
==
REP_SEARCH
);
for
(
i
=
0
;
i
<
dc
->
dc_ds
->
ds_nattrs
;
i
++
)
{
Attribute
*
a
;
a
=
attr_find
(
rs
->
sr_entry
->
e_attrs
,
dc
->
dc_ds
->
ds_an
[
i
].
an_desc
);
if
(
a
&&
a
->
a_numvals
>
1
)
{
nattrs
++
;
}
}
if
(
!
nattrs
)
{
return
SLAP_CB_CONTINUE
;
}
rs_ensure_entry_modifiable
(
op
,
rs
,
dc
->
dc_on
);
rs
->
sr_flags
&=
~
(
REP_ENTRY_MODIFIABLE
|
REP_ENTRY_MUSTBEFREED
);
e
=
rs
->
sr_entry
;
valnum
=
op
->
o_tmpcalloc
(
sizeof
(
valnum_t
),
nattrs
,
op
->
o_tmpmemctx
);
for
(
c
=
0
,
i
=
0
;
i
<
dc
->
dc_ds
->
ds_nattrs
;
i
++
)
{
for
(
app
=
&
e
->
e_attrs
;
*
app
!=
NULL
;
app
=
&
(
*
app
)
->
a_next
)
{
if
(
(
*
app
)
->
a_desc
==
dc
->
dc_ds
->
ds_an
[
i
].
an_desc
)
{
break
;
}
}
if
(
*
app
!=
NULL
&&
(
*
app
)
->
a_numvals
>
1
)
{
valnum
[
c
].
ap
=
*
app
;
*
app
=
(
*
app
)
->
a_next
;
valnum
[
c
].
ap
->
a_next
=
ap_list
;
ap_list
=
valnum
[
c
].
ap
;
valnum
[
c
].
a
=
*
valnum
[
c
].
ap
;
if
(
c
<
nattrs
-
1
)
{
valnum
[
c
].
a
.
a_next
=
&
valnum
[
c
+
1
].
a
;
}
else
{
valnum
[
c
].
a
.
a_next
=
NULL
;
}
valnum
[
c
].
a
.
a_numvals
=
1
;
valnum
[
c
].
a
.
a_vals
=
valnum
[
c
].
vals
;
BER_BVZERO
(
&
valnum
[
c
].
vals
[
1
]
);
if
(
valnum
[
c
].
ap
->
a_nvals
!=
valnum
[
c
].
ap
->
a_vals
)
{
valnum
[
c
].
a
.
a_nvals
=
valnum
[
c
].
nvals
;
BER_BVZERO
(
&
valnum
[
c
].
nvals
[
1
]
);
}
else
{
valnum
[
c
].
a
.
a_nvals
=
valnum
[
c
].
a
.
a_vals
;
}
c
++
;
}
}
for
(
app
=
&
e
->
e_attrs
;
*
app
!=
NULL
;
app
=
&
(
*
app
)
->
a_next
)
/* goto tail */
;
*
app
=
&
valnum
[
0
].
a
;
/* NOTE: since send_search_entry() does not honor the
* REP_CTRLS_MUSTBEFREED flag set by slap_add_ctrls(),
* the control could be added here once for all (ITS#6629)
*/
dc
->
dc_skip
=
1
;
rc
=
dupent_response_entry_1level
(
op
,
rs
,
e
,
valnum
,
nattrs
,
0
);
dc
->
dc_skip
=
0
;
*
app
=
ap_list
;
entry_free
(
e
);
op
->
o_tmpfree
(
valnum
,
op
->
o_tmpmemctx
);
return
rc
;
}
static
int
dupent_response
(
Operation
*
op
,
SlapReply
*
rs
)
{
dupent_cb_t
*
dc
=
(
dupent_cb_t
*
)
op
->
o_callback
->
sc_private
;
if
(
dc
->
dc_skip
)
{
return
SLAP_CB_CONTINUE
;
}
switch
(
rs
->
sr_type
)
{
case
REP_RESULT
:
return
dupent_response_done
(
op
,
rs
);
case
REP_SEARCH
:
return
dupent_response_entry
(
op
,
rs
);
case
REP_SEARCHREF
:
break
;
default:
assert
(
0
);
}
return
SLAP_CB_CONTINUE
;
}
static
int
dupent_cleanup
(
Operation
*
op
,
SlapReply
*
rs
)
{
if
(
rs
->
sr_type
==
REP_RESULT
||
rs
->
sr_err
==
SLAPD_ABANDON
)
{
op
->
o_tmpfree
(
op
->
o_callback
,
op
->
o_tmpmemctx
);
op
->
o_callback
=
NULL
;
op
->
o_tmpfree
(
op
->
o_ctrldupent
,
op
->
o_tmpmemctx
);
op
->
o_ctrldupent
=
NULL
;
}
return
SLAP_CB_CONTINUE
;
}
static
int
dupent_op_search
(
Operation
*
op
,
SlapReply
*
rs
)
{
if
(
op
->
o_dupent
!=
SLAP_CONTROL_NONE
)
{
slap_callback
*
sc
;
dupent_cb_t
*
dc
;
sc
=
op
->
o_tmpcalloc
(
1
,
sizeof
(
slap_callback
)
+
sizeof
(
dupent_cb_t
),
op
->
o_tmpmemctx
);
dc
=
(
dupent_cb_t
*
)
&
sc
[
1
];
dc
->
dc_on
=
(
slap_overinst
*
)
op
->
o_bd
->
bd_info
;
dc
->
dc_ds
=
(
dupent_t
*
)
op
->
o_ctrldupent
;
dc
->
dc_skip
=
0
;
sc
->
sc_response
=
dupent_response
;
sc
->
sc_cleanup
=
dupent_cleanup
;
sc
->
sc_private
=
(
void
*
)
dc
;
sc
->
sc_next
=
op
->
o_callback
->
sc_next
;
op
->
o_callback
->
sc_next
=
sc
;
}
return
SLAP_CB_CONTINUE
;
}
#if SLAPD_OVER_DUPENT == SLAPD_MOD_DYNAMIC
static
#endif
/* SLAPD_OVER_DUPENT == SLAPD_MOD_DYNAMIC */
int
dupent_initialize
(
void
)
{
int
rc
;
rc
=
register_supported_control
(
LDAP_CONTROL_DUPENT
,
SLAP_CTRL_SEARCH
,
NULL
,
dupent_parseCtrl
,
&
dupent_cid
);
if
(
rc
!=
LDAP_SUCCESS
)
{
Debug
(
LDAP_DEBUG_ANY
,
"dupent_initialize: Failed to register control (%d)
\n
"
,
rc
,
0
,
0
);
return
-
1
;
}
dupent
.
on_bi
.
bi_type
=
"dupent"
;
dupent
.
on_bi
.
bi_op_search
=
dupent_op_search
;
return
overlay_register
(
&
dupent
);
}
#if SLAPD_OVER_DUPENT == SLAPD_MOD_DYNAMIC
int
init_module
(
int
argc
,
char
*
argv
[]
)
{
return
dupent_initialize
();
}
#endif
/* SLAPD_OVER_DUPENT == SLAPD_MOD_DYNAMIC */
#endif
/* SLAPD_OVER_DUPENT */
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment