Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Nadezhda Ivanova
OpenLDAP
Commits
c809208d
Commit
c809208d
authored
Feb 25, 2021
by
Ondřej Kuzník
Committed by
Quanah Gibson-Mount
Mar 26, 2021
Browse files
ITS#9472 Add datamorph overlay
parent
0b1ad3fc
Changes
39
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/datamorph/.gitignore
0 → 100644
View file @
c809208d
# test suite
clients
servers
contrib/slapd-modules/datamorph/Makefile
0 → 100644
View file @
c809208d
# $OpenLDAP$
# This work is part of OpenLDAP Software <http://www.openldap.org/>.
#
# Copyright 1998-2021 The OpenLDAP Foundation.
# Copyright 2017 Ondřej Kuzník, 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>.
LDAP_SRC
=
../../..
LDAP_BUILD
=
$(LDAP_SRC)
SRCDIR
=
./
LDAP_INC
=
-I
$(LDAP_BUILD)
/include
-I
$(LDAP_SRC)
/include
-I
$(LDAP_SRC)
/servers/slapd
LDAP_LIB
=
$(LDAP_BUILD)
/libraries/libldap/libldap.la
\
$(LDAP_BUILD)
/libraries/liblber/liblber.la
LIBTOOL
=
$(LDAP_BUILD)
/libtool
INSTALL
=
/usr/bin/install
CC
=
gcc
OPT
=
-g
-O2
-Wall
DEFS
=
-DSLAPD_OVER_DATAMORPH
=
SLAPD_MOD_DYNAMIC
INCS
=
$(LDAP_INC)
LIBS
=
$(LDAP_LIB)
PROGRAMS
=
datamorph.la
MANPAGES
=
slapo-datamorph.5
CLEAN
=
*
.o
*
.lo
*
.la .libs
LTVER
=
0:0:0
prefix
=
/usr/local
exec_prefix
=
$(prefix)
ldap_subdir
=
/openldap
libdir
=
$(exec_prefix)
/lib
libexecdir
=
$(exec_prefix)
/libexec
moduledir
=
$(libexecdir)$(ldap_subdir)
mandir
=
$(exec_prefix)
/share/man
man5dir
=
$(mandir)
/man5
all
:
$(PROGRAMS)
d
:=
sp
:=
dir
:=
tests
include
$(dir)/Rules.mk
%.lo
:
%.c
$(LIBTOOL)
--mode
=
compile
$(CC)
$(OPT)
$(DEFS)
$(INCS)
-c
$<
%.la
:
%.lo
$(LIBTOOL)
--mode
=
link
$(CC)
$(OPT)
-version-info
$(LTVER)
\
-rpath
$(moduledir)
-module
-o
$@
$?
$(LIBS)
clean
:
rm
-rf
$(CLEAN)
install
:
install-lib install-man FORCE
install-lib
:
$(PROGRAMS)
mkdir
-p
$(DESTDIR)$(moduledir)
for
p
in
$(PROGRAMS)
;
do
\
$(LIBTOOL)
--mode
=
install cp
$$
p
$(DESTDIR)$(moduledir)
;
\
done
install-man
:
$(MANPAGES)
mkdir
-p
$(DESTDIR)$(man5dir)
$(INSTALL)
-m
644
$(MANPAGES)
$(DESTDIR)$(man5dir)
FORCE
:
contrib/slapd-modules/datamorph/datamorph.c
0 → 100644
View file @
c809208d
/* datamorph.c - enumerated and native integer value support */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2016-2021 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 developed in 2016 by Ondřej Kuzník for Symas Corp.
*/
#include
"portable.h"
#ifdef SLAPD_OVER_DATAMORPH
#include
<inttypes.h>
#include
<ac/stdlib.h>
#if defined(__linux__)
#include
<endian.h>
#elif defined(sun)
#define be16toh(x) BE_16(x)
#define le16toh(x) LE_16(x)
#define htobe16(x) BE_16(x)
#define htole16(x) LE_16(x)
#define be32toh(x) BE_32(x)
#define le32toh(x) LE_32(x)
#define htobe32(x) BE_32(x)
#define htole32(x) LE_32(x)
#define be64toh(x) BE_64(x)
#define le64toh(x) LE_64(x)
#define htobe64(x) BE_64(x)
#define htole64(x) LE_64(x)
#elif defined(__NetBSD__) || defined(__FreeBSD__)
#include
<sys/endian.h>
#elif defined(__OpenBSD__)
#include
<sys/endian.h>
#define be16toh(x) betoh16(x)
#define le16toh(x) letoh16(x)
#define be32toh(x) betoh32(x)
#define le32toh(x) letoh32(x)
#define be64toh(x) betoh64(x)
#define le64toh(x) letoh64(x)
#elif defined(__BYTE_ORDER__) && \
( defined(__GNUC__) || defined(__clang__) )
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define be16toh(x) __builtin_bswap16(x)
#define le16toh(x) (x)
#define htobe16(x) __builtin_bswap16(x)
#define htole16(x) (x)
#define be32toh(x) __builtin_bswap32(x)
#define le32toh(x) (x)
#define htobe32(x) __builtin_bswap32(x)
#define htole32(x) (x)
#define be64toh(x) __builtin_bswap64(x)
#define le64toh(x) (x)
#define htobe64(x) __builtin_bswap64(x)
#define htole64(x) (x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define be16toh(x) (x)
#define le16toh(x) __builtin_bswap16(x)
#define htobe16(x) (x)
#define htole16(x) __builtin_bswap16(x)
#define be32toh(x) (x)
#define le32toh(x) __builtin_bswap32(x)
#define htobe32(x) (x)
#define htole32(x) __builtin_bswap32(x)
#define be64toh(x) (x)
#define le64toh(x) __builtin_bswap64(x)
#define htobe64(x) (x)
#define htole64(x) __builtin_bswap64(x)
#else
#error "Only support pure big and little endian at the moment"
#endif
#else
#error "I lack the way to check my endianness and convert to/from big-endian"
#endif
#include
"slap.h"
#include
"slap-config.h"
#include
"lutil.h"
#include
"ldap_queue.h"
typedef
enum
datamorph_type_t
{
DATAMORPH_UNSET
,
DATAMORPH_ENUM
,
DATAMORPH_INT
,
}
datamorph_type
;
typedef
enum
datamorph_flags_t
{
DATAMORPH_FLAG_SIGNED
=
1
<<
0
,
DATAMORPH_FLAG_LOWER
=
1
<<
1
,
DATAMORPH_FLAG_UPPER
=
1
<<
2
,
}
datamorph_flags
;
typedef
union
datamorph_interval_bound_t
{
int64_t
i
;
uint64_t
u
;
}
datamorph_interval_bound
;
typedef
struct
transformation_info_t
{
AttributeDescription
*
attr
;
datamorph_type
type
;
union
{
struct
{
Avlnode
*
to_db
;
struct
berval
from_db
[
256
];
}
maps
;
#define ti_enum info.maps
struct
{
datamorph_flags
flags
;
unsigned
int
size
;
datamorph_interval_bound
lower
,
upper
;
}
interval
;
#define ti_int info.interval
}
info
;
}
transformation_info
;
typedef
struct
datamorph_enum_mapping_t
{
struct
berval
wire_value
;
uint8_t
db_value
;
transformation_info
*
transformation
;
}
datamorph_enum_mapping
;
typedef
struct
datamorph_info_t
{
Avlnode
*
transformations
;
transformation_info
*
wip_transformation
;
}
datamorph_info
;
static
int
transformation_mapping_cmp
(
const
void
*
l
,
const
void
*
r
)
{
const
datamorph_enum_mapping
*
left
=
l
,
*
right
=
r
;
return
ber_bvcmp
(
&
left
->
wire_value
,
&
right
->
wire_value
);
}
static
int
transformation_info_cmp
(
const
void
*
l
,
const
void
*
r
)
{
const
transformation_info
*
left
=
l
,
*
right
=
r
;
return
(
left
->
attr
==
right
->
attr
)
?
0
:
(
left
->
attr
<
right
->
attr
)
?
-
1
:
1
;
}
static
int
transform_to_db_format_one
(
Operation
*
op
,
transformation_info
*
definition
,
struct
berval
*
value
,
struct
berval
*
outval
)
{
switch
(
definition
->
type
)
{
case
DATAMORPH_ENUM
:
{
datamorph_enum_mapping
*
mapping
,
needle
=
{
.
wire_value
=
*
value
};
struct
berval
db_value
=
{
.
bv_len
=
1
};
mapping
=
avl_find
(
definition
->
ti_enum
.
to_db
,
&
needle
,
transformation_mapping_cmp
);
if
(
!
mapping
)
{
Debug
(
LDAP_DEBUG_ANY
,
"transform_to_db_format_one: "
"value '%s' not mapped
\n
"
,
value
->
bv_val
);
return
LDAP_CONSTRAINT_VIOLATION
;
}
db_value
.
bv_val
=
(
char
*
)
&
mapping
->
db_value
;
ber_dupbv
(
outval
,
&
db_value
);
assert
(
outval
->
bv_val
);
break
;
}
case
DATAMORPH_INT
:
{
union
{
char
s
[
8
];
uint8_t
be8
;
uint16_t
be16
;
uint32_t
be32
;
uint64_t
be64
;
}
buf
;
struct
berval
db_value
=
{
.
bv_val
=
buf
.
s
};
char
*
ptr
=
value
->
bv_val
+
value
->
bv_len
;
uint64_t
unsigned_value
;
int64_t
signed_value
;
assert
(
definition
->
ti_int
.
size
==
1
||
definition
->
ti_int
.
size
==
2
||
definition
->
ti_int
.
size
==
4
||
definition
->
ti_int
.
size
==
8
);
/* Read number */
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
signed_value
=
strtoll
(
value
->
bv_val
,
&
ptr
,
10
);
}
else
{
unsigned_value
=
strtoull
(
value
->
bv_val
,
&
ptr
,
10
);
}
if
(
*
value
->
bv_val
==
'\0'
||
*
ptr
!=
'\0'
)
{
Debug
(
LDAP_DEBUG_ANY
,
"transform_to_db_format_one: "
"value '%s' not an integer
\n
"
,
value
->
bv_val
);
return
LDAP_CONSTRAINT_VIOLATION
;
}
/* Check it's within configured bounds */
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
if
(
signed_value
<
definition
->
ti_int
.
lower
.
i
||
signed_value
>
definition
->
ti_int
.
upper
.
i
)
{
Debug
(
LDAP_DEBUG_ANY
,
"transform_to_db_format_one: "
"value '%s' doesn't fit configured constraints
\n
"
,
value
->
bv_val
);
return
LDAP_CONSTRAINT_VIOLATION
;
}
}
else
{
if
(
unsigned_value
<
definition
->
ti_int
.
lower
.
u
||
unsigned_value
>
definition
->
ti_int
.
upper
.
u
)
{
Debug
(
LDAP_DEBUG_ANY
,
"transform_to_db_format_one: "
"value '%s' doesn't fit configured constraints
\n
"
,
value
->
bv_val
);
return
LDAP_CONSTRAINT_VIOLATION
;
}
}
db_value
.
bv_len
=
definition
->
ti_int
.
size
;
switch
(
definition
->
ti_int
.
size
)
{
case
1
:
{
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
buf
.
be8
=
(
unsigned
char
)((
char
)
signed_value
);
}
else
{
buf
.
be8
=
unsigned_value
;
}
break
;
}
case
2
:
{
uint16_t
h16
;
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
h16
=
signed_value
;
}
else
{
h16
=
unsigned_value
;
}
buf
.
be16
=
htobe16
(
h16
);
break
;
}
case
4
:
{
uint32_t
h32
;
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
h32
=
signed_value
;
}
else
{
h32
=
unsigned_value
;
}
buf
.
be32
=
htobe32
(
h32
);
break
;
}
case
8
:
{
uint64_t
h64
;
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
h64
=
signed_value
;
}
else
{
h64
=
unsigned_value
;
}
buf
.
be64
=
htobe64
(
h64
);
break
;
}
}
ber_dupbv
(
outval
,
&
db_value
);
assert
(
outval
->
bv_val
);
break
;
}
default:
assert
(
0
);
}
return
LDAP_SUCCESS
;
}
static
int
transform_to_db_format
(
Operation
*
op
,
transformation_info
*
definition
,
BerVarray
values
,
int
numvals
,
BerVarray
*
out
)
{
struct
berval
*
value
;
int
i
,
rc
=
LDAP_SUCCESS
;
if
(
numvals
==
0
)
{
for
(
value
=
values
;
value
;
value
++
,
numvals
++
)
;
/* Count them */
}
assert
(
out
);
*
out
=
ch_calloc
(
numvals
+
1
,
sizeof
(
struct
berval
)
);
for
(
i
=
0
;
i
<
numvals
;
i
++
)
{
rc
=
transform_to_db_format_one
(
op
,
definition
,
&
values
[
i
],
&
(
*
out
)[
i
]
);
if
(
rc
)
{
break
;
}
}
if
(
rc
)
{
for
(
;
i
>=
0
;
i
--
)
{
ch_free
((
*
out
)[
i
].
bv_val
);
}
ch_free
(
*
out
);
}
return
rc
;
}
static
int
transform_from_db_format_one
(
Operation
*
op
,
transformation_info
*
definition
,
struct
berval
*
value
,
struct
berval
*
outval
)
{
switch
(
definition
->
type
)
{
case
DATAMORPH_ENUM
:
{
uint8_t
index
=
value
->
bv_val
[
0
];
struct
berval
*
val
=
&
definition
->
info
.
maps
.
from_db
[
index
];
if
(
!
BER_BVISNULL
(
val
)
)
{
ber_dupbv
(
outval
,
val
);
assert
(
outval
->
bv_val
);
}
else
{
Debug
(
LDAP_DEBUG_ANY
,
"transform_from_db_format_one: "
"DB value %d has no mapping!
\n
"
,
index
);
/* FIXME: probably still need to return an error */
BER_BVZERO
(
outval
);
}
break
;
}
case
DATAMORPH_INT
:
{
char
buf
[
24
];
struct
berval
wire_value
=
{
.
bv_val
=
buf
};
union
lens_t
{
uint8_t
be8
;
uint16_t
be16
;
uint32_t
be32
;
uint64_t
be64
;
}
*
lens
=
(
union
lens_t
*
)
value
->
bv_val
;
uint64_t
unsigned_value
;
int64_t
signed_value
;
if
(
value
->
bv_len
!=
definition
->
ti_int
.
size
)
{
Debug
(
LDAP_DEBUG_ANY
,
"transform_from_db_format_one(%s): "
"unexpected DB value of length %lu when configured "
"for %u!
\n
"
,
definition
->
attr
->
ad_cname
.
bv_val
,
value
->
bv_len
,
definition
->
ti_int
.
size
);
/* FIXME: probably still need to return an error */
BER_BVZERO
(
outval
);
break
;
}
assert
(
definition
->
ti_int
.
size
==
1
||
definition
->
ti_int
.
size
==
2
||
definition
->
ti_int
.
size
==
4
||
definition
->
ti_int
.
size
==
8
);
switch
(
definition
->
ti_int
.
size
)
{
case
1
:
{
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
signed_value
=
(
int8_t
)
lens
->
be8
;
}
else
{
unsigned_value
=
(
uint8_t
)
lens
->
be8
;
}
break
;
}
case
2
:
{
uint16_t
h16
=
be16toh
(
lens
->
be16
);
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
signed_value
=
(
int16_t
)
h16
;
}
else
{
unsigned_value
=
(
uint16_t
)
h16
;
}
break
;
}
case
4
:
{
uint32_t
h32
=
be32toh
(
lens
->
be32
);
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
signed_value
=
(
int32_t
)
h32
;
}
else
{
unsigned_value
=
(
uint32_t
)
h32
;
}
break
;
}
case
8
:
{
uint64_t
h64
=
be64toh
(
lens
->
be64
);
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
signed_value
=
(
int64_t
)
h64
;
}
else
{
unsigned_value
=
(
uint64_t
)
h64
;
}
break
;
}
}
if
(
definition
->
ti_int
.
flags
&
DATAMORPH_FLAG_SIGNED
)
{
wire_value
.
bv_len
=
sprintf
(
buf
,
"%"
PRId64
,
signed_value
);
}
else
{
wire_value
.
bv_len
=
sprintf
(
buf
,
"%"
PRIu64
,
unsigned_value
);
}
ber_dupbv
(
outval
,
&
wire_value
);
assert
(
outval
->
bv_val
);
break
;
}
default:
assert
(
0
);
}
return
LDAP_SUCCESS
;
}
static
int
transform_from_db_format
(
Operation
*
op
,
transformation_info
*
definition
,
BerVarray
values
,
int
numvals
,
BerVarray
*
out
)
{
struct
berval
*
value
;
int
i
,
rc
=
LDAP_SUCCESS
;
if
(
numvals
==
0
)
{
for
(
value
=
values
;
value
;
value
++
,
numvals
++
)
;
/* Count them */
}
assert
(
out
);
*
out
=
ch_calloc
(
numvals
+
1
,
sizeof
(
struct
berval
)
);
for
(
i
=
0
;
i
<
numvals
;
i
++
)
{
struct
berval
bv
;
rc
=
transform_from_db_format_one
(
op
,
definition
,
&
values
[
i
],
&
bv
);
if
(
!
BER_BVISNULL
(
&
bv
)
)
{
ber_bvarray_add
(
out
,
&
bv
);
}
if
(
rc
)
{
break
;
}
}
if
(
rc
)
{
for
(
;
i
>=
0
;
i
--
)
{
ch_free
(
(
*
out
)[
i
].
bv_val
);
}
ch_free
(
*
out
);
}
return
rc
;
}
static
int
datamorph_filter
(
Operation
*
op
,
datamorph_info
*
ov
,
Filter
*
f
)
{
switch
(
f
->
f_choice
)
{
case
LDAP_FILTER_PRESENT
:
/* The matching rules are not in place,
* so the filter will be ignored */
case
LDAP_FILTER_APPROX
:
case
LDAP_FILTER_SUBSTRINGS
:
default:
break
;
return
LDAP_SUCCESS
;
case
LDAP_FILTER_AND
:
case
LDAP_FILTER_OR
:
{
for
(
f
=
f
->
f_and
;
f
;
f
=
f
->
f_next
)
{
int
rc
=
datamorph_filter
(
op
,
ov
,
f
);
if
(
rc
!=
LDAP_SUCCESS
)
{
return
rc
;
}
}
}
break
;
case
LDAP_FILTER_NOT
:
return
datamorph_filter
(
op
,
ov
,
f
->
f_not
);
case
LDAP_FILTER_EQUALITY
:
case
LDAP_FILTER_GE
:
case
LDAP_FILTER_LE
:
{
transformation_info
*
t
,
needle
=
{
.
attr
=
f
->
f_ava
->
aa_desc
};
t
=
avl_find
(
ov
->
transformations
,
&
needle
,
transformation_info_cmp
);
if
(
t
)
{
struct
berval
new_val
;
int
rc
=
transform_to_db_format_one
(
op
,
t
,
&
f
->
f_ava
->
aa_value
,
&
new_val
);
ch_free
(
f
->
f_ava
->
aa_value
.
bv_val
);