Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Utility functions for the dbwrap API
4 : Copyright (C) Volker Lendecke 2007
5 : Copyright (C) Michael Adam 2009
6 : Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
7 :
8 : Major code contributions from Aleksey Fedoseev (fedoseev@ru.ibm.com)
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 2 of the License, or
13 : (at your option) any later version.
14 :
15 : This program 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
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program; if not, write to the Free Software
22 : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 : */
24 :
25 : #include "includes.h"
26 : #include "dbwrap.h"
27 : #include "lib/util/util_tdb.h"
28 :
29 : struct dbwrap_fetch_int32_state {
30 : NTSTATUS status;
31 : int32_t result;
32 : };
33 :
34 27202 : static void dbwrap_fetch_int32_parser(TDB_DATA key, TDB_DATA data,
35 : void *private_data)
36 : {
37 27202 : struct dbwrap_fetch_int32_state *state =
38 : (struct dbwrap_fetch_int32_state *)private_data;
39 :
40 27202 : if (data.dsize != sizeof(state->result)) {
41 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
42 0 : return;
43 : }
44 27202 : state->result = IVAL(data.dptr, 0);
45 27202 : state->status = NT_STATUS_OK;
46 : }
47 :
48 29785 : NTSTATUS dbwrap_fetch_int32(struct db_context *db, TDB_DATA key,
49 : int32_t *result)
50 : {
51 278 : struct dbwrap_fetch_int32_state state;
52 278 : NTSTATUS status;
53 :
54 29785 : if (result == NULL) {
55 0 : return NT_STATUS_INVALID_PARAMETER;
56 : }
57 :
58 29785 : state.status = NT_STATUS_INTERNAL_ERROR;
59 :
60 29785 : status = dbwrap_parse_record(db, key, dbwrap_fetch_int32_parser, &state);
61 29785 : if (!NT_STATUS_IS_OK(status)) {
62 2583 : return status;
63 : }
64 :
65 27202 : if (NT_STATUS_IS_OK(state.status)) {
66 27202 : *result = state.result;
67 : }
68 27202 : return state.status;
69 : }
70 :
71 27604 : NTSTATUS dbwrap_fetch_int32_bystring(struct db_context *db, const char *keystr,
72 : int32_t *result)
73 : {
74 27604 : return dbwrap_fetch_int32(db, string_term_tdb_data(keystr), result);
75 : }
76 :
77 380 : NTSTATUS dbwrap_store_int32_bystring(struct db_context *db, const char *keystr,
78 : int32_t v)
79 : {
80 22 : uint8_t v_store[sizeof(int32_t)];
81 380 : TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
82 22 : NTSTATUS status;
83 :
84 380 : SIVAL(v_store, 0, v);
85 :
86 380 : status = dbwrap_store(db, string_term_tdb_data(keystr), data,
87 : TDB_REPLACE);
88 380 : return status;
89 : }
90 :
91 : struct dbwrap_fetch_uint32_state {
92 : NTSTATUS status;
93 : uint32_t result;
94 : };
95 :
96 252430 : static void dbwrap_fetch_uint32_parser(TDB_DATA key, TDB_DATA data,
97 : void *private_data)
98 : {
99 252430 : struct dbwrap_fetch_uint32_state *state =
100 : (struct dbwrap_fetch_uint32_state *)private_data;
101 :
102 252430 : if (data.dsize != sizeof(state->result)) {
103 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
104 0 : return;
105 : }
106 252430 : state->result = IVAL(data.dptr, 0);
107 252430 : state->status = NT_STATUS_OK;
108 : }
109 :
110 253653 : NTSTATUS dbwrap_fetch_uint32_bystring(struct db_context *db,
111 : const char *keystr, uint32_t *val)
112 : {
113 231 : struct dbwrap_fetch_uint32_state state;
114 231 : NTSTATUS status;
115 :
116 253653 : if (val == NULL) {
117 0 : return NT_STATUS_INVALID_PARAMETER;
118 : }
119 :
120 253653 : state.status = NT_STATUS_INTERNAL_ERROR;
121 :
122 253653 : status = dbwrap_parse_record(db, string_term_tdb_data(keystr),
123 : dbwrap_fetch_uint32_parser, &state);
124 253653 : if (!NT_STATUS_IS_OK(status)) {
125 1223 : return status;
126 : }
127 252430 : if (NT_STATUS_IS_OK(state.status)) {
128 252430 : *val = state.result;
129 : }
130 252430 : return state.status;
131 : }
132 :
133 160 : NTSTATUS dbwrap_store_uint32_bystring(struct db_context *db,
134 : const char *keystr, uint32_t v)
135 : {
136 8 : uint8_t v_store[sizeof(uint32_t)];
137 160 : TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
138 8 : NTSTATUS status;
139 :
140 160 : SIVAL(v_store, 0, v);
141 :
142 160 : status = dbwrap_store(db, string_term_tdb_data(keystr), data,
143 : TDB_REPLACE);
144 160 : return status;
145 : }
146 :
147 : /**
148 : * Atomic unsigned integer change (addition):
149 : *
150 : * if value does not exist yet in the db, use *oldval as initial old value.
151 : * return old value in *oldval.
152 : * store *oldval + change_val to db.
153 : */
154 :
155 : struct dbwrap_change_uint32_atomic_context {
156 : const char *keystr;
157 : uint32_t *oldval;
158 : uint32_t change_val;
159 : NTSTATUS status;
160 : };
161 :
162 1264 : static void dbwrap_change_uint32_atomic_action_fn(struct db_record *rec,
163 : TDB_DATA value,
164 : void *private_data)
165 : {
166 1264 : struct dbwrap_change_uint32_atomic_context *state = private_data;
167 108 : uint8_t v_store[4];
168 1264 : TDB_DATA data = {
169 : .dptr = v_store,
170 : .dsize = sizeof(v_store),
171 : };
172 1264 : uint32_t val = UINT32_MAX;
173 :
174 1264 : if (value.dptr == NULL) {
175 0 : val = *(state->oldval);
176 1264 : } else if (value.dsize == sizeof(val)) {
177 1264 : val = PULL_LE_U32(value.dptr, 0);
178 1264 : *(state->oldval) = val;
179 : } else {
180 0 : state->status = NT_STATUS_UNSUCCESSFUL;
181 0 : return;
182 : }
183 :
184 1264 : val += state->change_val;
185 1264 : PUSH_LE_U32(v_store, 0, val);
186 :
187 1264 : state->status = dbwrap_record_store(rec, data, TDB_REPLACE);
188 : }
189 :
190 1264 : static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
191 : void *private_data)
192 : {
193 1264 : struct dbwrap_change_uint32_atomic_context *state = private_data;
194 108 : NTSTATUS status;
195 :
196 1264 : status = dbwrap_do_locked(db,
197 : string_term_tdb_data(state->keystr),
198 : dbwrap_change_uint32_atomic_action_fn,
199 : state);
200 1264 : if (!NT_STATUS_IS_OK(status)) {
201 0 : DBG_DEBUG("dbwrap_do_locked() failed: %s\n",
202 : nt_errstr(status));
203 0 : return status;
204 : }
205 1264 : if (!NT_STATUS_IS_OK(state->status)) {
206 0 : DBG_DEBUG("dbwrap_change_uint32_atomic_action_fn() "
207 : "failed: %s\n",
208 : nt_errstr(status));
209 0 : return status;
210 : }
211 1264 : return NT_STATUS_OK;
212 : }
213 :
214 108 : NTSTATUS dbwrap_change_uint32_atomic_bystring(struct db_context *db,
215 : const char *keystr,
216 : uint32_t *oldval,
217 : uint32_t change_val)
218 : {
219 108 : NTSTATUS ret;
220 108 : struct dbwrap_change_uint32_atomic_context state;
221 :
222 108 : state.keystr = keystr;
223 108 : state.oldval = oldval;
224 108 : state.change_val = change_val;
225 :
226 108 : ret = dbwrap_change_uint32_atomic_action(db, &state);
227 :
228 108 : return ret;
229 : }
230 :
231 1156 : NTSTATUS dbwrap_trans_change_uint32_atomic_bystring(struct db_context *db,
232 : const char *keystr,
233 : uint32_t *oldval,
234 : uint32_t change_val)
235 : {
236 0 : NTSTATUS ret;
237 0 : struct dbwrap_change_uint32_atomic_context state;
238 :
239 1156 : state.keystr = keystr;
240 1156 : state.oldval = oldval;
241 1156 : state.change_val = change_val;
242 :
243 1156 : ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
244 :
245 1156 : return ret;
246 : }
247 :
248 : /**
249 : * Atomic integer change (addition):
250 : *
251 : * if value does not exist yet in the db, use *oldval as initial old value.
252 : * return old value in *oldval.
253 : * store *oldval + change_val to db.
254 : */
255 :
256 : struct dbwrap_change_int32_atomic_context {
257 : TDB_DATA key;
258 : int32_t *oldval;
259 : int32_t change_val;
260 : NTSTATUS status;
261 : };
262 :
263 5604 : static void dbwrap_change_int32_atomic_action_fn(struct db_record *rec,
264 : TDB_DATA value,
265 : void *private_data)
266 : {
267 5604 : struct dbwrap_change_int32_atomic_context *state = private_data;
268 36 : uint8_t v_store[4];
269 5604 : TDB_DATA data = {
270 : .dptr = v_store,
271 : .dsize = sizeof(v_store),
272 : };
273 5604 : int32_t val = -1;
274 :
275 5604 : if (value.dptr == NULL) {
276 404 : val = *(state->oldval);
277 5200 : } else if (value.dsize == sizeof(val)) {
278 5200 : val = PULL_LE_U32(value.dptr, 0);
279 5200 : *(state->oldval) = val;
280 : } else {
281 0 : state->status = NT_STATUS_UNSUCCESSFUL;
282 0 : return;
283 : }
284 :
285 5604 : val += state->change_val;
286 5604 : PUSH_LE_U32(v_store, 0, val);
287 :
288 5604 : state->status = dbwrap_record_store(rec, data, TDB_REPLACE);
289 : }
290 :
291 5604 : static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
292 : void *private_data)
293 : {
294 5604 : struct dbwrap_change_int32_atomic_context *state = private_data;
295 36 : NTSTATUS status;
296 :
297 5604 : status = dbwrap_do_locked(db,
298 : state->key,
299 : dbwrap_change_int32_atomic_action_fn,
300 : state);
301 5604 : if (!NT_STATUS_IS_OK(status)) {
302 0 : DBG_DEBUG("dbwrap_do_locked() failed: %s\n",
303 : nt_errstr(status));
304 0 : return status;
305 : }
306 5604 : if (!NT_STATUS_IS_OK(state->status)) {
307 0 : DBG_DEBUG("dbwrap_change_int32_atomic_action_fn() "
308 : "failed: %s\n",
309 : nt_errstr(status));
310 0 : return status;
311 : }
312 5604 : return NT_STATUS_OK;
313 : }
314 :
315 5604 : NTSTATUS dbwrap_change_int32_atomic(struct db_context *db,
316 : TDB_DATA key,
317 : int32_t *oldval,
318 : int32_t change_val)
319 : {
320 36 : NTSTATUS ret;
321 36 : struct dbwrap_change_int32_atomic_context state;
322 :
323 5604 : state.key = key;
324 5604 : state.oldval = oldval;
325 5604 : state.change_val = change_val;
326 :
327 5604 : ret = dbwrap_change_int32_atomic_action(db, &state);
328 :
329 5604 : return ret;
330 : }
331 :
332 0 : NTSTATUS dbwrap_change_int32_atomic_bystring(struct db_context *db,
333 : const char *keystr,
334 : int32_t *oldval,
335 : int32_t change_val)
336 : {
337 0 : return dbwrap_change_int32_atomic(db, string_term_tdb_data(keystr),
338 : oldval, change_val);
339 : }
340 :
341 0 : NTSTATUS dbwrap_trans_change_int32_atomic_bystring(struct db_context *db,
342 : const char *keystr,
343 : int32_t *oldval,
344 : int32_t change_val)
345 : {
346 0 : NTSTATUS ret;
347 0 : struct dbwrap_change_int32_atomic_context state;
348 :
349 0 : state.key = string_term_tdb_data(keystr);
350 0 : state.oldval = oldval;
351 0 : state.change_val = change_val;
352 :
353 0 : ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
354 :
355 0 : return ret;
356 : }
357 :
358 : struct dbwrap_store_context {
359 : TDB_DATA *key;
360 : TDB_DATA *dbuf;
361 : int flag;
362 : };
363 :
364 20820 : static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
365 : {
366 219 : NTSTATUS status;
367 219 : struct dbwrap_store_context *store_ctx;
368 :
369 20820 : store_ctx = (struct dbwrap_store_context *)private_data;
370 :
371 20820 : status = dbwrap_store(db, *(store_ctx->key), *(store_ctx->dbuf),
372 : store_ctx->flag);
373 20820 : if (!NT_STATUS_IS_OK(status)) {
374 0 : DEBUG(5, ("store returned %s\n", nt_errstr(status)));
375 : }
376 :
377 20820 : return status;
378 : }
379 :
380 20820 : NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
381 : int flag)
382 : {
383 219 : NTSTATUS status;
384 219 : struct dbwrap_store_context store_ctx;
385 :
386 20820 : store_ctx.key = &key;
387 20820 : store_ctx.dbuf = &dbuf;
388 20820 : store_ctx.flag = flag;
389 :
390 20820 : status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
391 :
392 20820 : return status;
393 : }
394 :
395 521 : static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
396 : {
397 9 : NTSTATUS status;
398 521 : TDB_DATA *key = (TDB_DATA *)private_data;
399 :
400 521 : status = dbwrap_delete(db, *key);
401 521 : if (!NT_STATUS_IS_OK(status)) {
402 7 : DBG_INFO("dbwrap_record_delete returned %s\n",
403 : nt_errstr(status));
404 : }
405 521 : return status;
406 : }
407 :
408 521 : NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
409 : {
410 9 : NTSTATUS status;
411 :
412 521 : status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
413 :
414 521 : return status;
415 : }
416 :
417 15 : NTSTATUS dbwrap_trans_store_int32_bystring(struct db_context *db,
418 : const char *keystr,
419 : int32_t v)
420 : {
421 1 : int32_t v_store;
422 :
423 15 : SIVAL(&v_store, 0, v);
424 :
425 15 : return dbwrap_trans_store(db, string_term_tdb_data(keystr),
426 : make_tdb_data((const uint8_t *)&v_store,
427 : sizeof(v_store)),
428 : TDB_REPLACE);
429 : }
430 :
431 992 : NTSTATUS dbwrap_trans_store_uint32_bystring(struct db_context *db,
432 : const char *keystr,
433 : uint32_t v)
434 : {
435 20 : uint32_t v_store;
436 :
437 992 : SIVAL(&v_store, 0, v);
438 :
439 992 : return dbwrap_trans_store(db, string_term_tdb_data(keystr),
440 : make_tdb_data((const uint8_t *)&v_store,
441 : sizeof(v_store)),
442 : TDB_REPLACE);
443 : }
444 :
445 16535 : NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
446 : TDB_DATA data, int flags)
447 : {
448 16535 : return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
449 : }
450 :
451 2 : NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
452 : {
453 2 : return dbwrap_trans_delete(db, string_term_tdb_data(key));
454 : }
455 :
456 : /**
457 : * Wrap db action(s) into a transaction.
458 : */
459 46272 : NTSTATUS dbwrap_trans_do(struct db_context *db,
460 : NTSTATUS (*action)(struct db_context *, void *),
461 : void *private_data)
462 : {
463 488 : int res;
464 488 : NTSTATUS status;
465 :
466 46272 : res = dbwrap_transaction_start(db);
467 46272 : if (res != 0) {
468 0 : DEBUG(5, ("transaction_start failed\n"));
469 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
470 : }
471 :
472 46272 : status = action(db, private_data);
473 46272 : if (!NT_STATUS_IS_OK(status)) {
474 11 : if (dbwrap_transaction_cancel(db) != 0) {
475 0 : smb_panic("Cancelling transaction failed");
476 : }
477 11 : return status;
478 : }
479 :
480 46261 : res = dbwrap_transaction_commit(db);
481 46261 : if (res == 0) {
482 46261 : return NT_STATUS_OK;
483 : }
484 :
485 0 : DEBUG(2, ("transaction_commit failed\n"));
486 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
487 : }
488 :
489 : struct dbwrap_trans_traverse_action_ctx {
490 : int (*f)(struct db_record* rec, void* private_data);
491 : void* private_data;
492 : };
493 :
494 :
495 0 : static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
496 : {
497 0 : struct dbwrap_trans_traverse_action_ctx* ctx =
498 : (struct dbwrap_trans_traverse_action_ctx*)private_data;
499 :
500 0 : NTSTATUS status = dbwrap_traverse(db, ctx->f, ctx->private_data, NULL);
501 :
502 0 : return status;
503 : }
504 :
505 0 : NTSTATUS dbwrap_trans_traverse(struct db_context *db,
506 : int (*f)(struct db_record*, void*),
507 : void *private_data)
508 : {
509 0 : struct dbwrap_trans_traverse_action_ctx ctx = {
510 : .f = f,
511 : .private_data = private_data,
512 : };
513 0 : return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
514 : }
515 :
516 8594 : NTSTATUS dbwrap_purge(struct db_context *db, TDB_DATA key)
517 : {
518 33 : NTSTATUS status;
519 :
520 8594 : status = dbwrap_delete(db, key);
521 8594 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
522 2150 : status = NT_STATUS_OK;
523 : }
524 :
525 8594 : return status;
526 : }
527 :
528 8483 : NTSTATUS dbwrap_purge_bystring(struct db_context *db, const char *key)
529 : {
530 8483 : return dbwrap_purge(db, string_term_tdb_data(key));
531 : }
532 :
533 144457 : NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key)
534 : {
535 144457 : return dbwrap_delete(db, string_term_tdb_data(key));
536 : }
537 :
538 1700084 : NTSTATUS dbwrap_store_bystring(struct db_context *db, const char *key,
539 : TDB_DATA data, int flags)
540 : {
541 1700084 : return dbwrap_store(db, string_term_tdb_data(key), data, flags);
542 : }
543 :
544 9685321 : NTSTATUS dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx,
545 : const char *key, TDB_DATA *value)
546 : {
547 9685321 : return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key), value);
548 : }
549 :
550 :
551 :
552 1594 : NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
553 : {
554 11 : char *key_upper;
555 11 : NTSTATUS status;
556 :
557 1594 : key_upper = talloc_strdup_upper(talloc_tos(), key);
558 1594 : if (key_upper == NULL) {
559 0 : return NT_STATUS_NO_MEMORY;
560 : }
561 :
562 1594 : status = dbwrap_delete_bystring(db, key_upper);
563 :
564 1594 : talloc_free(key_upper);
565 1594 : return status;
566 : }
567 :
568 1468878 : NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
569 : TDB_DATA data, int flags)
570 : {
571 506 : char *key_upper;
572 506 : NTSTATUS status;
573 :
574 1468878 : key_upper = talloc_strdup_upper(talloc_tos(), key);
575 1468878 : if (key_upper == NULL) {
576 0 : return NT_STATUS_NO_MEMORY;
577 : }
578 :
579 1468878 : status = dbwrap_store_bystring(db, key_upper, data, flags);
580 :
581 1468878 : talloc_free(key_upper);
582 1468878 : return status;
583 : }
584 :
585 1067022 : NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
586 : const char *key, TDB_DATA *value)
587 : {
588 318 : char *key_upper;
589 318 : NTSTATUS status;
590 :
591 1067022 : key_upper = talloc_strdup_upper(talloc_tos(), key);
592 1067022 : if (key_upper == NULL) {
593 0 : return NT_STATUS_NO_MEMORY;
594 : }
595 :
596 1067022 : status = dbwrap_fetch_bystring(db, mem_ctx, key_upper, value);
597 :
598 1067022 : talloc_free(key_upper);
599 1067022 : return status;
600 : }
601 :
602 : struct dbwrap_marshall_state {
603 : uint8_t *buf;
604 : size_t bufsize;
605 : size_t dbsize;
606 : };
607 :
608 0 : static int dbwrap_marshall_fn(struct db_record *rec, void *private_data)
609 : {
610 0 : struct dbwrap_marshall_state *state = private_data;
611 0 : TDB_DATA key, value;
612 0 : size_t new_dbsize;
613 :
614 0 : key = dbwrap_record_get_key(rec);
615 0 : value = dbwrap_record_get_value(rec);
616 :
617 0 : new_dbsize = state->dbsize;
618 0 : new_dbsize += 8 + key.dsize;
619 0 : new_dbsize += 8 + value.dsize;
620 :
621 0 : if (new_dbsize <= state->bufsize) {
622 0 : uint8_t *p = state->buf + state->dbsize;
623 :
624 0 : SBVAL(p, 0, key.dsize);
625 0 : p += 8;
626 0 : memcpy(p, key.dptr, key.dsize);
627 0 : p += key.dsize;
628 :
629 0 : SBVAL(p, 0, value.dsize);
630 0 : p += 8;
631 0 : memcpy(p, value.dptr, value.dsize);
632 : }
633 0 : state->dbsize = new_dbsize;
634 0 : return 0;
635 : }
636 :
637 0 : size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize)
638 : {
639 0 : struct dbwrap_marshall_state state;
640 :
641 0 : state.bufsize = bufsize;
642 0 : state.buf = buf;
643 0 : state.dbsize = 0;
644 :
645 0 : dbwrap_traverse_read(db, dbwrap_marshall_fn, &state, NULL);
646 :
647 0 : return state.dbsize;
648 : }
649 :
650 10 : static ssize_t dbwrap_unmarshall_get_data(const uint8_t *buf, size_t buflen,
651 : size_t ofs, TDB_DATA *pdata)
652 : {
653 0 : uint64_t space, len;
654 0 : const uint8_t *p;
655 :
656 10 : if (ofs == buflen) {
657 6 : return 0;
658 : }
659 4 : if (ofs > buflen) {
660 0 : return -1;
661 : }
662 :
663 4 : space = buflen - ofs;
664 4 : if (space < 8) {
665 0 : return -1;
666 : }
667 :
668 4 : p = buf + ofs;
669 4 : len = BVAL(p, 0);
670 :
671 4 : p += 8;
672 4 : space -= 8;
673 :
674 4 : if (len > space) {
675 0 : return -1;
676 : }
677 :
678 4 : *pdata = (TDB_DATA) { .dptr = discard_const_p(uint8_t, p),
679 : .dsize = len };
680 4 : return len + 8;
681 : }
682 :
683 6 : NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
684 : bool (*fn)(TDB_DATA key, TDB_DATA value,
685 : void *private_data),
686 : void *private_data)
687 : {
688 6 : size_t ofs = 0;
689 :
690 2 : while (true) {
691 0 : ssize_t len;
692 0 : TDB_DATA key, value;
693 0 : bool ok;
694 :
695 8 : len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &key);
696 8 : if (len == 0) {
697 6 : break;
698 : }
699 2 : if (len == -1) {
700 0 : return NT_STATUS_INVALID_PARAMETER;
701 : }
702 2 : ofs += len;
703 :
704 2 : len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &value);
705 2 : if (len == 0) {
706 0 : break;
707 : }
708 2 : if (len == -1) {
709 0 : return NT_STATUS_INVALID_PARAMETER;
710 : }
711 2 : ofs += len;
712 :
713 2 : ok = fn(key, value, private_data);
714 2 : if (!ok) {
715 0 : break;
716 : }
717 : }
718 :
719 6 : return NT_STATUS_OK;
720 : }
721 :
722 : struct dbwrap_unmarshall_state {
723 : struct db_context *db;
724 : NTSTATUS ret;
725 : };
726 :
727 0 : static bool dbwrap_unmarshall_fn(TDB_DATA key, TDB_DATA value,
728 : void *private_data)
729 : {
730 0 : struct dbwrap_unmarshall_state *state = private_data;
731 0 : NTSTATUS status;
732 :
733 0 : status = dbwrap_store(state->db, key, value, 0);
734 0 : if (!NT_STATUS_IS_OK(status)) {
735 0 : DBG_DEBUG("dbwrap_record_store failed: %s\n",
736 : nt_errstr(status));
737 0 : state->ret = status;
738 0 : return false;
739 : }
740 :
741 0 : return true;
742 : }
743 :
744 0 : NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
745 : size_t buflen)
746 : {
747 0 : struct dbwrap_unmarshall_state state = { .db = db };
748 0 : NTSTATUS status;
749 :
750 0 : status = dbwrap_parse_marshall_buf(buf, buflen,
751 : dbwrap_unmarshall_fn, &state);
752 0 : if (!NT_STATUS_IS_OK(status)) {
753 0 : return status;
754 : }
755 0 : return state.ret;
756 : }
|