4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb pack/unpack
29 * Description: pack/unpack routines for ldb messages as key/value blobs
31 * Author: Andrew Tridgell
36 /* change this if the data format ever changes */
37 #define LTDB_PACKING_FORMAT 0x26011967
39 /* use a portable integer format */
40 static void put_uint32(uint8_t *p
, int ofs
, unsigned int val
)
44 p
[1] = (val
>>8) & 0xFF;
45 p
[2] = (val
>>16) & 0xFF;
46 p
[3] = (val
>>24) & 0xFF;
49 static unsigned int pull_uint32(uint8_t *p
, int ofs
)
52 return p
[0] | (p
[1]<<8) | (p
[2]<<16) | (p
[3]<<24);
55 static int attribute_storable_values(const struct ldb_message_element
*el
)
57 if (el
->num_values
== 0) return 0;
59 if (ldb_attr_cmp(el
->name
, "dn") == 0) return 0;
61 if (ldb_attr_cmp(el
->name
, "distinguishedName") == 0) return 0;
63 return el
->num_values
;
67 pack a ldb message into a linear buffer in a TDB_DATA
69 note that this routine avoids saving elements with zero values,
70 as these are equivalent to having no element
72 caller frees the data buffer after use
74 int ltdb_pack_data(struct ldb_module
*module
,
75 const struct ldb_message
*message
,
76 struct TDB_DATA
*data
)
78 struct ldb_context
*ldb
;
79 unsigned int i
, j
, real_elements
=0;
85 ldb
= ldb_module_get_ctx(module
);
87 dn
= ldb_dn_get_linearized(message
->dn
);
93 /* work out how big it needs to be */
96 size
+= 1 + strlen(dn
);
98 for (i
=0;i
<message
->num_elements
;i
++) {
99 if (attribute_storable_values(&message
->elements
[i
]) == 0) {
105 size
+= 1 + strlen(message
->elements
[i
].name
) + 4;
106 for (j
=0;j
<message
->elements
[i
].num_values
;j
++) {
107 size
+= 4 + message
->elements
[i
].values
[j
].length
+ 1;
112 data
->dptr
= talloc_array(ldb
, uint8_t, size
);
120 put_uint32(p
, 0, LTDB_PACKING_FORMAT
);
121 put_uint32(p
, 4, real_elements
);
124 /* the dn needs to be packed so we can be case preserving
125 while hashing on a case folded dn */
127 memcpy(p
, dn
, len
+1);
130 for (i
=0;i
<message
->num_elements
;i
++) {
131 if (attribute_storable_values(&message
->elements
[i
]) == 0) {
134 len
= strlen(message
->elements
[i
].name
);
135 memcpy(p
, message
->elements
[i
].name
, len
+1);
137 put_uint32(p
, 0, message
->elements
[i
].num_values
);
139 for (j
=0;j
<message
->elements
[i
].num_values
;j
++) {
140 put_uint32(p
, 0, message
->elements
[i
].values
[j
].length
);
141 memcpy(p
+4, message
->elements
[i
].values
[j
].data
,
142 message
->elements
[i
].values
[j
].length
);
143 p
[4+message
->elements
[i
].values
[j
].length
] = 0;
144 p
+= 4 + message
->elements
[i
].values
[j
].length
+ 1;
152 unpack a ldb message from a linear buffer in TDB_DATA
154 Free with ltdb_unpack_data_free()
156 int ltdb_unpack_data(struct ldb_module
*module
,
157 const struct TDB_DATA
*data
,
158 struct ldb_message
*message
)
160 struct ldb_context
*ldb
;
162 unsigned int remaining
;
167 ldb
= ldb_module_get_ctx(module
);
168 message
->elements
= NULL
;
171 if (data
->dsize
< 8) {
176 format
= pull_uint32(p
, 0);
177 message
->num_elements
= pull_uint32(p
, 4);
180 remaining
= data
->dsize
- 8;
183 case LTDB_PACKING_FORMAT
:
184 len
= strnlen((char *)p
, remaining
);
185 if (len
== remaining
) {
189 message
->dn
= ldb_dn_new(message
, ldb
, (char *)p
);
190 if (message
->dn
== NULL
) {
194 remaining
-= len
+ 1;
203 if (message
->num_elements
== 0) {
204 message
->elements
= NULL
;
208 if (message
->num_elements
> remaining
/ 6) {
213 message
->elements
= talloc_array(message
, struct ldb_message_element
, message
->num_elements
);
214 if (!message
->elements
) {
219 memset(message
->elements
, 0,
220 message
->num_elements
* sizeof(struct ldb_message_element
));
222 for (i
=0;i
<message
->num_elements
;i
++) {
223 if (remaining
< 10) {
227 len
= strnlen((char *)p
, remaining
-6);
228 if (len
== remaining
-6) {
236 message
->elements
[i
].flags
= 0;
237 message
->elements
[i
].name
= talloc_strndup(message
->elements
, (char *)p
, len
);
238 if (message
->elements
[i
].name
== NULL
) {
242 remaining
-= len
+ 1;
244 message
->elements
[i
].num_values
= pull_uint32(p
, 0);
245 message
->elements
[i
].values
= NULL
;
246 if (message
->elements
[i
].num_values
!= 0) {
247 message
->elements
[i
].values
= talloc_array(message
->elements
,
249 message
->elements
[i
].num_values
);
250 if (!message
->elements
[i
].values
) {
257 for (j
=0;j
<message
->elements
[i
].num_values
;j
++) {
258 len
= pull_uint32(p
, 0);
259 if (len
> remaining
-5) {
264 message
->elements
[i
].values
[j
].length
= len
;
265 message
->elements
[i
].values
[j
].data
= talloc_size(message
->elements
[i
].values
, len
+1);
266 if (message
->elements
[i
].values
[j
].data
== NULL
) {
270 memcpy(message
->elements
[i
].values
[j
].data
, p
+4, len
);
271 message
->elements
[i
].values
[j
].data
[len
] = 0;
273 remaining
-= len
+4+1;
278 if (remaining
!= 0) {
279 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
280 "Error: %d bytes unread in ltdb_unpack_data", remaining
);
286 talloc_free(message
->elements
);