LCOV - code coverage report
Current view: top level - source3/locking - leases_db.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 197 298 66.1 %
Date: 2024-02-28 12:06:22 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Map lease keys to file ids
       4             :    Copyright (C) Volker Lendecke 2013
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : 
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "locking/leases_db.h"
      24             : #include "dbwrap/dbwrap.h"
      25             : #include "dbwrap/dbwrap_open.h"
      26             : #include "util_tdb.h"
      27             : #include "ndr.h"
      28             : #include "librpc/gen_ndr/ndr_leases_db.h"
      29             : 
      30             : #undef DBGC_CLASS
      31             : #define DBGC_CLASS DBGC_LOCKING
      32             : 
      33             : /* the leases database handle */
      34             : static struct db_context *leases_db;
      35             : 
      36        6410 : bool leases_db_init(bool read_only)
      37             : {
      38           0 :         char *db_path;
      39             : 
      40        6410 :         if (leases_db) {
      41        6410 :                 return true;
      42             :         }
      43             : 
      44           0 :         db_path = lock_path(talloc_tos(), "leases.tdb");
      45           0 :         if (db_path == NULL) {
      46           0 :                 return false;
      47             :         }
      48             : 
      49           0 :         leases_db = db_open(NULL, db_path,
      50             :                             SMBD_VOLATILE_TDB_HASH_SIZE,
      51             :                             SMBD_VOLATILE_TDB_FLAGS |
      52             :                             TDB_SEQNUM,
      53             :                             read_only ? O_RDONLY : O_RDWR|O_CREAT, 0644,
      54             :                             DBWRAP_LOCK_ORDER_4, DBWRAP_FLAG_NONE);
      55           0 :         TALLOC_FREE(db_path);
      56           0 :         if (leases_db == NULL) {
      57           0 :                 DEBUG(1, ("ERROR: Failed to initialise leases database\n"));
      58           0 :                 return false;
      59             :         }
      60             : 
      61           0 :         return true;
      62             : }
      63             : 
      64             : struct leases_db_key_buf {
      65             :         uint8_t buf[32];
      66             : };
      67             : 
      68        6290 : static TDB_DATA leases_db_key(struct leases_db_key_buf *buf,
      69             :                               const struct GUID *client_guid,
      70             :                               const struct smb2_lease_key *lease_key)
      71             : {
      72        6290 :         struct leases_db_key db_key = {
      73             :                 .client_guid = *client_guid,
      74             :                 .lease_key = *lease_key };
      75        6290 :         DATA_BLOB blob = { .data = buf->buf, .length = sizeof(buf->buf) };
      76           0 :         enum ndr_err_code ndr_err;
      77             : 
      78        6290 :         if (DEBUGLEVEL >= 10) {
      79           0 :                 DBG_DEBUG("\n");
      80           0 :                 NDR_PRINT_DEBUG(leases_db_key, &db_key);
      81             :         }
      82             : 
      83        6290 :         ndr_err = ndr_push_struct_into_fixed_blob(
      84             :                 &blob, &db_key, (ndr_push_flags_fn_t)ndr_push_leases_db_key);
      85        6290 :         SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
      86             : 
      87        6290 :         return (TDB_DATA) { .dptr = buf->buf, .dsize = sizeof(buf->buf) };
      88             : }
      89             : 
      90             : struct leases_db_do_locked_state {
      91             :         void (*fn)(struct leases_db_value *value,
      92             :                    bool *modified,
      93             :                    void *private_data);
      94             :         void *private_data;
      95             :         NTSTATUS status;
      96             : };
      97             : 
      98        1920 : static void leases_db_do_locked_fn(
      99             :         struct db_record *rec,
     100             :         TDB_DATA db_value,
     101             :         void *private_data)
     102             : {
     103        1920 :         struct leases_db_do_locked_state *state = private_data;
     104        1920 :         DATA_BLOB blob = { .data = db_value.dptr, .length = db_value.dsize };
     105        1920 :         struct leases_db_value *value = NULL;
     106           0 :         enum ndr_err_code ndr_err;
     107        1920 :         bool modified = false;
     108             : 
     109        1920 :         value = talloc_zero(talloc_tos(), struct leases_db_value);
     110        1920 :         if (value == NULL) {
     111           0 :                 state->status = NT_STATUS_NO_MEMORY;
     112           0 :                 goto done;
     113             :         }
     114             : 
     115        1920 :         if (blob.length != 0) {
     116        1162 :                 ndr_err = ndr_pull_struct_blob_all(
     117             :                         &blob,
     118             :                         value,
     119             :                         value,
     120             :                         (ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
     121        1162 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     122           0 :                         DBG_ERR("ndr_pull_struct_blob_failed: %s\n",
     123             :                                   ndr_errstr(ndr_err));
     124           0 :                         state->status = ndr_map_error2ntstatus(ndr_err);
     125           0 :                         goto done;
     126             :                 }
     127             :         }
     128             : 
     129        1920 :         state->fn(value, &modified, state->private_data);
     130             : 
     131        1920 :         if (!modified) {
     132           0 :                 goto done;
     133             :         }
     134             : 
     135        1920 :         if (value->num_files == 0) {
     136         750 :                 state->status = dbwrap_record_delete(rec);
     137         750 :                 if (!NT_STATUS_IS_OK(state->status)) {
     138           0 :                         DBG_ERR("dbwrap_record_delete returned %s\n",
     139             :                                   nt_errstr(state->status));
     140             :                 }
     141         750 :                 goto done;
     142             :         }
     143             : 
     144        1170 :         ndr_err = ndr_push_struct_blob(
     145             :                 &blob,
     146             :                 value,
     147             :                 value,
     148             :                 (ndr_push_flags_fn_t)ndr_push_leases_db_value);
     149        1170 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     150           0 :                 DBG_ERR("ndr_push_struct_blob_failed: %s\n",
     151             :                           ndr_errstr(ndr_err));
     152           0 :                 state->status = ndr_map_error2ntstatus(ndr_err);
     153           0 :                 goto done;
     154             :         }
     155             : 
     156        1170 :         if (DEBUGLEVEL >= 10) {
     157           0 :                 DBG_DEBUG("\n");
     158           0 :                 NDR_PRINT_DEBUG(leases_db_value, value);
     159             :         }
     160             : 
     161        1170 :         db_value = make_tdb_data(blob.data, blob.length);
     162             : 
     163        1170 :         state->status = dbwrap_record_store(rec, db_value, 0);
     164        1170 :         if (!NT_STATUS_IS_OK(state->status)) {
     165           0 :                 DBG_ERR("dbwrap_record_store returned %s\n",
     166             :                           nt_errstr(state->status));
     167             :         }
     168             : 
     169        1170 : done:
     170        1920 :         TALLOC_FREE(value);
     171        1920 : }
     172             : 
     173        1920 : static NTSTATUS leases_db_do_locked(
     174             :         const struct GUID *client_guid,
     175             :         const struct smb2_lease_key *lease_key,
     176             :         void (*fn)(struct leases_db_value *value,
     177             :                    bool *modified,
     178             :                    void *private_data),
     179             :         void *private_data)
     180             : {
     181           0 :         struct leases_db_key_buf keybuf;
     182        1920 :         TDB_DATA db_key = leases_db_key(&keybuf, client_guid, lease_key);
     183        1920 :         struct leases_db_do_locked_state state = {
     184             :                 .fn = fn, .private_data = private_data,
     185             :         };
     186           0 :         NTSTATUS status;
     187             : 
     188        1920 :         if (!leases_db_init(false)) {
     189           0 :                 return NT_STATUS_INTERNAL_ERROR;
     190             :         }
     191             : 
     192        1920 :         status = dbwrap_do_locked(
     193             :                 leases_db, db_key, leases_db_do_locked_fn, &state);
     194        1920 :         if (!NT_STATUS_IS_OK(status)) {
     195           0 :                 return status;
     196             :         }
     197        1920 :         return state.status;
     198             : }
     199             : 
     200             : struct leases_db_add_state {
     201             :         const struct file_id *id;
     202             :         uint32_t current_state;
     203             :         uint16_t lease_version;
     204             :         uint16_t epoch;
     205             :         const char *servicepath;
     206             :         const char *base_name;
     207             :         const char *stream_name;
     208             :         NTSTATUS status;
     209             : };
     210             : 
     211         760 : static void leases_db_add_fn(
     212             :         struct leases_db_value *value, bool *modified, void *private_data)
     213             : {
     214         760 :         struct leases_db_add_state *state = private_data;
     215         760 :         struct leases_db_file *tmp = NULL;
     216           0 :         uint32_t i;
     217             : 
     218             :         /* id must be unique. */
     219         762 :         for (i = 0; i < value->num_files; i++) {
     220           2 :                 if (file_id_equal(state->id, &value->files[i].id)) {
     221           0 :                         state->status = NT_STATUS_OBJECT_NAME_COLLISION;
     222           0 :                         return;
     223             :                 }
     224             :         }
     225             : 
     226         760 :         if (value->num_files == 0) {
     227             :                 /* new record */
     228         758 :                 value->current_state = state->current_state;
     229         758 :                 value->lease_version = state->lease_version;
     230         758 :                 value->epoch = state->epoch;
     231             :         }
     232             : 
     233         760 :         tmp = talloc_realloc(
     234             :                 value,
     235             :                 value->files,
     236             :                 struct leases_db_file,
     237             :                 value->num_files + 1);
     238         760 :         if (tmp == NULL) {
     239           0 :                 state->status = NT_STATUS_NO_MEMORY;
     240           0 :                 return;
     241             :         }
     242         760 :         value->files = tmp;
     243             : 
     244         760 :         value->files[value->num_files] = (struct leases_db_file) {
     245         760 :                 .id = *state->id,
     246         760 :                 .servicepath = state->servicepath,
     247         760 :                 .base_name = state->base_name,
     248         760 :                 .stream_name = state->stream_name,
     249             :         };
     250         760 :         value->num_files += 1;
     251             : 
     252         760 :         *modified = true;
     253             : }
     254             : 
     255         760 : NTSTATUS leases_db_add(const struct GUID *client_guid,
     256             :                        const struct smb2_lease_key *lease_key,
     257             :                        const struct file_id *id,
     258             :                        uint32_t current_state,
     259             :                        uint16_t lease_version,
     260             :                        uint16_t epoch,
     261             :                        const char *servicepath,
     262             :                        const char *base_name,
     263             :                        const char *stream_name)
     264             : {
     265         760 :         struct leases_db_add_state state = {
     266             :                 .id = id,
     267             :                 .current_state = current_state,
     268             :                 .lease_version = lease_version,
     269             :                 .epoch = epoch,
     270             :                 .servicepath = servicepath,
     271             :                 .base_name = base_name,
     272             :                 .stream_name = stream_name,
     273             :         };
     274           0 :         NTSTATUS status;
     275             : 
     276         760 :         status = leases_db_do_locked(
     277             :                 client_guid, lease_key, leases_db_add_fn, &state);
     278         760 :         if (!NT_STATUS_IS_OK(status)) {
     279           0 :                 DBG_DEBUG("leases_db_do_locked failed: %s\n",
     280             :                           nt_errstr(status));
     281           0 :                 return status;
     282             :         }
     283         760 :         return state.status;
     284             : }
     285             : 
     286             : struct leases_db_del_state {
     287             :         const struct file_id *id;
     288             :         NTSTATUS status;
     289             : };
     290             : 
     291         752 : static void leases_db_del_fn(
     292             :         struct leases_db_value *value, bool *modified, void *private_data)
     293             : {
     294         752 :         struct leases_db_del_state *state = private_data;
     295           0 :         uint32_t i;
     296             : 
     297         752 :         for (i = 0; i < value->num_files; i++) {
     298         752 :                 if (file_id_equal(state->id, &value->files[i].id)) {
     299         752 :                         break;
     300             :                 }
     301             :         }
     302         752 :         if (i == value->num_files) {
     303           0 :                 state->status = NT_STATUS_NOT_FOUND;
     304           0 :                 return;
     305             :         }
     306             : 
     307         752 :         value->files[i] = value->files[value->num_files-1];
     308         752 :         value->num_files -= 1;
     309             : 
     310         752 :         *modified = true;
     311             : }
     312             : 
     313         752 : NTSTATUS leases_db_del(const struct GUID *client_guid,
     314             :                        const struct smb2_lease_key *lease_key,
     315             :                        const struct file_id *id)
     316             : {
     317         752 :         struct leases_db_del_state state = { .id = id };
     318           0 :         NTSTATUS status;
     319             : 
     320         752 :         status = leases_db_do_locked(
     321             :                 client_guid, lease_key, leases_db_del_fn, &state);
     322         752 :         if (!NT_STATUS_IS_OK(status)) {
     323           0 :                 DBG_DEBUG("leases_db_do_locked failed: %s\n",
     324             :                           nt_errstr(status));
     325           0 :                 return status;
     326             :         }
     327         752 :         return state.status;
     328             : }
     329             : 
     330             : struct leases_db_fetch_state {
     331             :         void (*parser)(uint32_t num_files,
     332             :                         const struct leases_db_file *files,
     333             :                         void *private_data);
     334             :         void *private_data;
     335             :         NTSTATUS status;
     336             : };
     337             : 
     338         360 : static void leases_db_parser(TDB_DATA key, TDB_DATA data, void *private_data)
     339             : {
     340         360 :         struct leases_db_fetch_state *state =
     341             :                 (struct leases_db_fetch_state *)private_data;
     342         360 :         DATA_BLOB blob = { .data = data.dptr, .length = data.dsize };
     343           0 :         enum ndr_err_code ndr_err;
     344           0 :         struct leases_db_value *value;
     345             : 
     346         360 :         value = talloc(talloc_tos(), struct leases_db_value);
     347         360 :         if (value == NULL) {
     348           0 :                 state->status = NT_STATUS_NO_MEMORY;
     349           0 :                 return;
     350             :         }
     351             : 
     352         360 :         ndr_err = ndr_pull_struct_blob_all(
     353             :                 &blob, value, value,
     354             :                 (ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
     355         360 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     356           0 :                 DEBUG(10, ("%s: ndr_pull_struct_blob_failed: %s\n",
     357             :                            __func__, ndr_errstr(ndr_err)));
     358           0 :                 TALLOC_FREE(value);
     359           0 :                 state->status = ndr_map_error2ntstatus(ndr_err);
     360           0 :                 return;
     361             :         }
     362             : 
     363         360 :         if (DEBUGLEVEL >= 10) {
     364           0 :                 DEBUG(10, ("%s:\n", __func__));
     365           0 :                 NDR_PRINT_DEBUG(leases_db_value, value);
     366             :         }
     367             : 
     368         360 :         state->parser(value->num_files,
     369         360 :                         value->files,
     370             :                         state->private_data);
     371             : 
     372         360 :         TALLOC_FREE(value);
     373         360 :         state->status = NT_STATUS_OK;
     374             : }
     375             : 
     376        1226 : NTSTATUS leases_db_parse(const struct GUID *client_guid,
     377             :                          const struct smb2_lease_key *lease_key,
     378             :                          void (*parser)(uint32_t num_files,
     379             :                                         const struct leases_db_file *files,
     380             :                                         void *private_data),
     381             :                          void *private_data)
     382             : {
     383           0 :         struct leases_db_key_buf keybuf;
     384        1226 :         TDB_DATA db_key = leases_db_key(&keybuf, client_guid, lease_key);
     385           0 :         struct leases_db_fetch_state state;
     386           0 :         NTSTATUS status;
     387             : 
     388        1226 :         if (!leases_db_init(true)) {
     389           0 :                 return NT_STATUS_INTERNAL_ERROR;
     390             :         }
     391             : 
     392        1226 :         state = (struct leases_db_fetch_state) {
     393             :                 .parser = parser,
     394             :                 .private_data = private_data,
     395             :                 .status = NT_STATUS_OK
     396             :         };
     397             : 
     398        1226 :         status = dbwrap_parse_record(leases_db, db_key, leases_db_parser,
     399             :                                      &state);
     400        1226 :         if (!NT_STATUS_IS_OK(status)) {
     401         866 :                 return status;
     402             :         }
     403         360 :         return state.status;
     404             : }
     405             : 
     406             : struct leases_db_rename_state {
     407             :         const struct file_id *id;
     408             :         const char *servicename_new;
     409             :         const char *filename_new;
     410             :         const char *stream_name_new;
     411             :         NTSTATUS status;
     412             : };
     413             : 
     414          10 : static void leases_db_rename_fn(
     415             :         struct leases_db_value *value, bool *modified, void *private_data)
     416             : {
     417          10 :         struct leases_db_rename_state *state = private_data;
     418          10 :         struct leases_db_file *file = NULL;
     419           0 :         uint32_t i;
     420             : 
     421             :         /* id must exist. */
     422          10 :         for (i = 0; i < value->num_files; i++) {
     423          10 :                 if (file_id_equal(state->id, &value->files[i].id)) {
     424          10 :                         break;
     425             :                 }
     426             :         }
     427          10 :         if (i == value->num_files) {
     428           0 :                 state->status = NT_STATUS_NOT_FOUND;
     429           0 :                 return;
     430             :         }
     431             : 
     432          10 :         file = &value->files[i];
     433          10 :         file->servicepath = state->servicename_new;
     434          10 :         file->base_name = state->filename_new;
     435          10 :         file->stream_name = state->stream_name_new;
     436             : 
     437          10 :         *modified = true;
     438             : }
     439             : 
     440          10 : NTSTATUS leases_db_rename(const struct GUID *client_guid,
     441             :                        const struct smb2_lease_key *lease_key,
     442             :                        const struct file_id *id,
     443             :                        const char *servicename_new,
     444             :                        const char *filename_new,
     445             :                        const char *stream_name_new)
     446             : {
     447          10 :         struct leases_db_rename_state state = {
     448             :                 .id = id,
     449             :                 .servicename_new = servicename_new,
     450             :                 .filename_new = filename_new,
     451             :                 .stream_name_new = stream_name_new,
     452             :         };
     453           0 :         NTSTATUS status;
     454             : 
     455          10 :         status = leases_db_do_locked(
     456             :                 client_guid, lease_key, leases_db_rename_fn, &state);
     457          10 :         if (!NT_STATUS_IS_OK(status)) {
     458           0 :                 DBG_DEBUG("leases_db_do_locked failed: %s\n",
     459             :                           nt_errstr(status));
     460           0 :                 return status;
     461             :         }
     462          10 :         return state.status;
     463             : }
     464             : 
     465             : struct leases_db_set_state {
     466             :         uint32_t current_state;
     467             :         bool breaking;
     468             :         uint32_t breaking_to_requested;
     469             :         uint32_t breaking_to_required;
     470             :         uint16_t lease_version;
     471             :         uint16_t epoch;
     472             : };
     473             : 
     474         398 : static void leases_db_set_fn(
     475             :         struct leases_db_value *value, bool *modified, void *private_data)
     476             : {
     477         398 :         struct leases_db_set_state *state = private_data;
     478             : 
     479         398 :         if (value->num_files == 0) {
     480           0 :                 DBG_WARNING("leases_db_set on new entry\n");
     481           0 :                 return;
     482             :         }
     483         398 :         value->current_state = state->current_state;
     484         398 :         value->breaking = state->breaking;
     485         398 :         value->breaking_to_requested = state->breaking_to_requested;
     486         398 :         value->breaking_to_required = state->breaking_to_required;
     487         398 :         value->lease_version = state->lease_version;
     488         398 :         value->epoch = state->epoch;
     489         398 :         *modified = true;
     490             : }
     491             : 
     492         398 : NTSTATUS leases_db_set(const struct GUID *client_guid,
     493             :                        const struct smb2_lease_key *lease_key,
     494             :                        uint32_t current_state,
     495             :                        bool breaking,
     496             :                        uint32_t breaking_to_requested,
     497             :                        uint32_t breaking_to_required,
     498             :                        uint16_t lease_version,
     499             :                        uint16_t epoch)
     500             : {
     501         398 :         struct leases_db_set_state state = {
     502             :                 .current_state = current_state,
     503             :                 .breaking = breaking,
     504             :                 .breaking_to_requested = breaking_to_requested,
     505             :                 .breaking_to_required = breaking_to_required,
     506             :                 .lease_version = lease_version,
     507             :                 .epoch = epoch,
     508             :         };
     509           0 :         NTSTATUS status;
     510             : 
     511         398 :         status = leases_db_do_locked(
     512             :                 client_guid, lease_key, leases_db_set_fn, &state);
     513         398 :         if (!NT_STATUS_IS_OK(status)) {
     514           0 :                 DBG_DEBUG("leases_db_do_locked failed: %s\n",
     515             :                           nt_errstr(status));
     516           0 :                 return status;
     517             :         }
     518         398 :         return NT_STATUS_OK;
     519             : }
     520             : 
     521             : struct leases_db_get_state {
     522             :         const struct file_id *file_id;
     523             :         uint32_t *current_state;
     524             :         bool *breaking;
     525             :         uint32_t *breaking_to_requested;
     526             :         uint32_t *breaking_to_required;
     527             :         uint16_t *lease_version;
     528             :         uint16_t *epoch;
     529             :         NTSTATUS status;
     530             : };
     531             : 
     532        1796 : static void leases_db_get_fn(TDB_DATA key, TDB_DATA data, void *private_data)
     533             : {
     534        1796 :         struct leases_db_get_state *state = private_data;
     535        1796 :         DATA_BLOB blob = { .data = data.dptr, .length = data.dsize };
     536           0 :         enum ndr_err_code ndr_err;
     537           0 :         struct leases_db_value *value;
     538           0 :         uint32_t i;
     539             : 
     540        1796 :         value = talloc(talloc_tos(), struct leases_db_value);
     541        1796 :         if (value == NULL) {
     542           0 :                 state->status = NT_STATUS_NO_MEMORY;
     543           0 :                 return;
     544             :         }
     545             : 
     546        1796 :         ndr_err = ndr_pull_struct_blob_all(
     547             :                 &blob, value, value,
     548             :                 (ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
     549        1796 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     550           0 :                 DBG_ERR("ndr_pull_struct_blob_failed: %s\n",
     551             :                         ndr_errstr(ndr_err));
     552           0 :                 TALLOC_FREE(value);
     553           0 :                 state->status = ndr_map_error2ntstatus(ndr_err);
     554           0 :                 return;
     555             :         }
     556             : 
     557        1796 :         if (DEBUGLEVEL >= 10) {
     558           0 :                 DBG_DEBUG("\n");
     559           0 :                 NDR_PRINT_DEBUG(leases_db_value, value);
     560             :         }
     561             : 
     562             :         /* id must exist. */
     563        1806 :         for (i = 0; i < value->num_files; i++) {
     564        1804 :                 if (file_id_equal(state->file_id, &value->files[i].id)) {
     565        1794 :                         break;
     566             :                 }
     567             :         }
     568             : 
     569        1796 :         if (i == value->num_files) {
     570           2 :                 state->status = NT_STATUS_NOT_FOUND;
     571           2 :                 TALLOC_FREE(value);
     572           2 :                 return;
     573             :         }
     574             : 
     575        1794 :         if (state->current_state != NULL) {
     576        1794 :                 *state->current_state = value->current_state;
     577           0 :         };
     578        1794 :         if (state->breaking != NULL) {
     579        1634 :                 *state->breaking = value->breaking;
     580           0 :         };
     581        1794 :         if (state->breaking_to_requested != NULL) {
     582         574 :                 *state->breaking_to_requested = value->breaking_to_requested;
     583           0 :         };
     584        1794 :         if (state->breaking_to_required != NULL) {
     585         574 :                 *state->breaking_to_required = value->breaking_to_required;
     586           0 :         };
     587        1794 :         if (state->lease_version != NULL) {
     588        1196 :                 *state->lease_version = value->lease_version;
     589           0 :         };
     590        1794 :         if (state->epoch != NULL) {
     591        1196 :                 *state->epoch = value->epoch;
     592           0 :         };
     593             : 
     594        1794 :         TALLOC_FREE(value);
     595        1794 :         state->status = NT_STATUS_OK;
     596             : }
     597             : 
     598        2554 : NTSTATUS leases_db_get(const struct GUID *client_guid,
     599             :                        const struct smb2_lease_key *lease_key,
     600             :                        const struct file_id *file_id,
     601             :                        uint32_t *current_state,
     602             :                        bool *breaking,
     603             :                        uint32_t *breaking_to_requested,
     604             :                        uint32_t *breaking_to_required,
     605             :                        uint16_t *lease_version,
     606             :                        uint16_t *epoch)
     607             : {
     608        2554 :         struct leases_db_get_state state = {
     609             :                 .file_id = file_id,
     610             :                 .current_state = current_state,
     611             :                 .breaking = breaking,
     612             :                 .breaking_to_requested = breaking_to_requested,
     613             :                 .breaking_to_required = breaking_to_required,
     614             :                 .lease_version = lease_version,
     615             :                 .epoch = epoch,
     616             :         };
     617           0 :         struct leases_db_key_buf keybuf;
     618        2554 :         TDB_DATA db_key = leases_db_key(&keybuf, client_guid, lease_key);
     619           0 :         NTSTATUS status;
     620             : 
     621        2554 :         if (!leases_db_init(true)) {
     622           0 :                 return NT_STATUS_INTERNAL_ERROR;
     623             :         }
     624             : 
     625        2554 :         status = dbwrap_parse_record(
     626             :                 leases_db, db_key, leases_db_get_fn, &state);
     627        2554 :         if (!NT_STATUS_IS_OK(status)) {
     628         758 :                 return status;
     629             :         }
     630        1796 :         return state.status;
     631             : }
     632             : 
     633             : struct leases_db_get_current_state_state {
     634             :         int seqnum;
     635             :         uint32_t current_state;
     636             :         NTSTATUS status;
     637             : };
     638             : 
     639             : /*
     640             :  * This function is an optimization that
     641             :  * relies on the fact that the
     642             :  * smb2_lease_state current_state
     643             :  * (which is a uint32_t size)
     644             :  * from struct leases_db_value is the first
     645             :  * entry in the ndr-encoded struct leases_db_value.
     646             :  * Read it without having to ndr decode all
     647             :  * the values in struct leases_db_value.
     648             :  */
     649             : 
     650         590 : static void leases_db_get_current_state_fn(
     651             :         TDB_DATA key, TDB_DATA data, void *private_data)
     652             : {
     653         590 :         struct leases_db_get_current_state_state *state = private_data;
     654           0 :         struct ndr_pull ndr;
     655           0 :         enum ndr_err_code ndr_err;
     656             : 
     657         590 :         if (data.dsize < sizeof(uint32_t)) {
     658           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     659           0 :                 return;
     660             :         }
     661             : 
     662         590 :         state->seqnum = dbwrap_get_seqnum(leases_db);
     663             : 
     664         590 :         ndr = (struct ndr_pull) {
     665         590 :                 .data = data.dptr, .data_size = data.dsize,
     666             :         };
     667         590 :         ndr_err = ndr_pull_uint32(&ndr, NDR_SCALARS, &state->current_state);
     668         590 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     669           0 :                 state->status = ndr_map_error2ntstatus(ndr_err);
     670             :         }
     671             : }
     672             : 
     673         710 : NTSTATUS leases_db_get_current_state(
     674             :         const struct GUID *client_guid,
     675             :         const struct smb2_lease_key *lease_key,
     676             :         int *database_seqnum,
     677             :         uint32_t *current_state)
     678             : {
     679         710 :         struct leases_db_get_current_state_state state = { 0 };
     680           0 :         struct leases_db_key_buf keybuf;
     681         710 :         TDB_DATA db_key = { 0 };
     682           0 :         NTSTATUS status;
     683             : 
     684         710 :         if (!leases_db_init(true)) {
     685           0 :                 return NT_STATUS_INTERNAL_ERROR;
     686             :         }
     687             : 
     688         710 :         state.seqnum = dbwrap_get_seqnum(leases_db);
     689         710 :         if (*database_seqnum == state.seqnum) {
     690         120 :                 return NT_STATUS_OK;
     691             :         }
     692             : 
     693         590 :         db_key = leases_db_key(&keybuf, client_guid, lease_key);
     694             : 
     695         590 :         status = dbwrap_parse_record(
     696             :                 leases_db, db_key, leases_db_get_current_state_fn, &state);
     697         590 :         if (!NT_STATUS_IS_OK(status)) {
     698           0 :                 return status;
     699             :         }
     700         590 :         *database_seqnum = state.seqnum;
     701         590 :         *current_state = state.current_state;
     702             : 
     703         590 :         return NT_STATUS_OK;
     704             : }
     705             : 
     706         146 : NTSTATUS leases_db_copy_file_ids(TALLOC_CTX *mem_ctx,
     707             :                         uint32_t num_files,
     708             :                         const struct leases_db_file *files,
     709             :                         struct file_id **pp_ids)
     710             : {
     711           0 :         uint32_t i;
     712         146 :         struct file_id *ids = talloc_array(mem_ctx,
     713             :                                 struct file_id,
     714             :                                 num_files);
     715         146 :         if (ids == NULL) {
     716           0 :                 return NT_STATUS_NO_MEMORY;
     717             :         }
     718             : 
     719         298 :         for (i = 0; i < num_files; i++) {
     720         152 :                 ids[i] = files[i].id;
     721             :         }
     722         146 :         *pp_ids = ids;
     723         146 :         return NT_STATUS_OK;
     724             : }

Generated by: LCOV version 1.14