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

Generated by: LCOV version 1.13