LCOV - code coverage report
Current view: top level - source3/utils - status_json.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 338 699 48.4 %
Date: 2023-11-21 12:31:41 Functions: 16 20 80.0 %

          Line data    Source code
       1             : /*
       2             :  * Samba Unix/Linux SMB client library
       3             :  * Json output
       4             :  * Copyright (C) Jule Anger 2022
       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             : #include "includes.h"
      21             : #include "smbprofile.h"
      22             : #include "lib/util/time_basic.h"
      23             : #include "conn_tdb.h"
      24             : #include "session.h"
      25             : #include "librpc/gen_ndr/open_files.h"
      26             : #include "status_json.h"
      27             : #include "../libcli/security/security.h"
      28             : #include "status.h"
      29             : #include "lib/util/server_id.h"
      30             : #include "lib/util/string_wrappers.h"
      31             : 
      32             : #include <jansson.h>
      33             : #include "audit_logging.h" /* various JSON helpers */
      34             : #include "auth/common_auth.h"
      35             : 
      36          18 : int add_general_information_to_json(struct traverse_state *state)
      37             : {
      38             :         int result;
      39             : 
      40          18 :         result = json_add_timestamp(&state->root_json);
      41          18 :         if (result < 0) {
      42           0 :                 return -1;
      43             :         }
      44             : 
      45          18 :         result = json_add_string(&state->root_json, "version", samba_version_string());
      46          18 :         if (result < 0) {
      47           0 :                 return -1;
      48             :         }
      49             : 
      50          18 :         result = json_add_string(&state->root_json, "smb_conf", get_dyn_CONFIGFILE());
      51          18 :         if (result < 0) {
      52           0 :                 return -1;
      53             :         }
      54             : 
      55          18 :         return 0;
      56             : }
      57             : 
      58          12 : static int add_server_id_to_json(struct json_object *parent_json,
      59             :                                  const struct server_id server_id)
      60             : {
      61             :         struct json_object sub_json;
      62          12 :         char *pid_str = NULL;
      63          12 :         char *task_id_str = NULL;
      64          12 :         char *vnn_str = NULL;
      65          12 :         char *unique_id_str = NULL;
      66             :         int result;
      67             : 
      68          12 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
      69          12 :         if (tmp_ctx == NULL) {
      70           0 :                 return -1;
      71             :         }
      72             : 
      73          12 :         sub_json = json_new_object();
      74          12 :         if (json_is_invalid(&sub_json)) {
      75           0 :                 goto failure;
      76             :         }
      77             : 
      78          12 :         pid_str = talloc_asprintf(
      79          12 :                 tmp_ctx, "%lu", (unsigned long)server_id.pid);
      80          12 :         result = json_add_string(&sub_json, "pid", pid_str);
      81          12 :         if (result < 0) {
      82           0 :                 goto failure;
      83             :         }
      84          12 :         task_id_str = talloc_asprintf(tmp_ctx, "%u", server_id.task_id);
      85          12 :         result = json_add_string(&sub_json, "task_id", task_id_str);
      86          12 :         if (result < 0) {
      87           0 :                 goto failure;
      88             :         }
      89          12 :         vnn_str = talloc_asprintf(tmp_ctx, "%u", server_id.vnn);
      90          12 :         result = json_add_string(&sub_json, "vnn", vnn_str);
      91          12 :         if (result < 0) {
      92           0 :                 goto failure;
      93             :         }
      94          12 :         unique_id_str = talloc_asprintf(
      95          12 :                 tmp_ctx, "%"PRIu64, server_id.unique_id);
      96          12 :         result = json_add_string(&sub_json, "unique_id", unique_id_str);
      97          12 :         if (result < 0) {
      98           0 :                 goto failure;
      99             :         }
     100             : 
     101          12 :         result = json_add_object(parent_json, "server_id", &sub_json);
     102          12 :         if (result < 0) {
     103           0 :                 goto failure;
     104             :         }
     105             : 
     106          12 :         TALLOC_FREE(tmp_ctx);
     107          12 :         return 0;
     108           0 : failure:
     109           0 :         json_free(&sub_json);
     110           0 :         TALLOC_FREE(tmp_ctx);
     111           0 :         return -1;
     112             : }
     113             : 
     114             : struct mask2txt {
     115             :         uint32_t mask;
     116             :         const char *string_desc;
     117             : };
     118             : 
     119             : /*
     120             :  * Convert a mask of some sort (access, oplock, leases),
     121             :  * to key/value pairs in a JSON object.
     122             :  */
     123          12 : static int map_mask_to_json(struct json_object *root_json,
     124             :                             uint32_t tomap,
     125             :                             const struct mask2txt *table)
     126             : {
     127          12 :         const struct mask2txt *a = NULL;
     128          12 :         int result = 0;
     129             : 
     130          92 :         for (a = table; a->string_desc != 0; a++) {
     131          80 :                 result = json_add_bool(root_json, a->string_desc,
     132          80 :                                       (tomap & a->mask) ? true : false);
     133             : 
     134          80 :                 if (result < 0) {
     135           0 :                         return result;
     136             :                 }
     137          80 :                 tomap &= ~a->mask;
     138             :         }
     139             : 
     140             :         /* Assert we know about all requested "tomap" values */
     141          12 :         SMB_ASSERT(tomap == 0);
     142             : 
     143          12 :         return 0;
     144             : }
     145             : 
     146             : static const struct mask2txt access_mask[] = {
     147             :         {FILE_READ_DATA, "READ_DATA"},
     148             :         {FILE_WRITE_DATA, "WRITE_DATA"},
     149             :         {FILE_APPEND_DATA, "APPEND_DATA"},
     150             :         {FILE_READ_EA, "READ_EA"},
     151             :         {FILE_WRITE_EA, "WRITE_EA"},
     152             :         {FILE_EXECUTE, "EXECUTE"},
     153             :         {FILE_READ_ATTRIBUTES, "READ_ATTRIBUTES"},
     154             :         {FILE_WRITE_ATTRIBUTES, "WRITE_ATTRIBUTES"},
     155             :         {FILE_DELETE_CHILD, "DELETE_CHILD"},
     156             :         {SEC_STD_DELETE, "DELETE"},
     157             :         {SEC_STD_READ_CONTROL, "READ_CONTROL"},
     158             :         {SEC_STD_WRITE_DAC, "WRITE_DAC"},
     159             :         {SEC_STD_SYNCHRONIZE, "SYNCHRONIZE"},
     160             :         {SEC_FLAG_SYSTEM_SECURITY, "ACCESS_SYSTEM_SECURITY"},
     161             :         {0, NULL}
     162             : };
     163             : 
     164             : static const struct mask2txt oplock_mask[] = {
     165             :         {EXCLUSIVE_OPLOCK, "EXCLUSIVE"},
     166             :         {BATCH_OPLOCK, "BATCH"},
     167             :         {LEVEL_II_OPLOCK, "LEVEL_II"},
     168             :         {LEASE_OPLOCK, "LEASE"},
     169             :         {0, NULL}
     170             : };
     171             : 
     172             : static const struct mask2txt sharemode_mask[] = {
     173             :         {FILE_SHARE_READ, "READ"},
     174             :         {FILE_SHARE_WRITE, "WRITE"},
     175             :         {FILE_SHARE_DELETE, "DELETE"},
     176             :         {0, NULL}
     177             : };
     178             : 
     179             : static const struct mask2txt lease_mask[] = {
     180             :         {SMB2_LEASE_READ, "READ"},
     181             :         {SMB2_LEASE_WRITE, "WRITE"},
     182             :         {SMB2_LEASE_HANDLE, "HANDLE"},
     183             :         {0, NULL}
     184             : };
     185             : 
     186         878 : int add_profile_item_to_json(struct traverse_state *state,
     187             :                              const char *section,
     188             :                              const char *subsection,
     189             :                              const char *key,
     190             :                              uintmax_t value)
     191             : {
     192         878 :         struct json_object section_json = {
     193             :                 .valid = false,
     194             :         };
     195         878 :         struct json_object subsection_json = {
     196             :                 .valid = false,
     197             :         };
     198         878 :         int result = 0;
     199             : 
     200         878 :         section_json = json_get_object(&state->root_json, section);
     201         878 :         if (json_is_invalid(&section_json)) {
     202           0 :                 goto failure;
     203             :         }
     204         878 :         subsection_json = json_get_object(&section_json, subsection);
     205         878 :         if (json_is_invalid(&subsection_json)) {
     206           0 :                 goto failure;
     207             :         }
     208             : 
     209         878 :         result = json_add_int(&subsection_json, key, value);
     210         878 :         if (result < 0) {
     211           0 :                 goto failure;
     212             :         }
     213             : 
     214         878 :         result = json_update_object(&section_json, subsection,  &subsection_json);
     215         878 :         if (result < 0) {
     216           0 :                 goto failure;
     217             :         }
     218         878 :         result = json_update_object(&state->root_json, section, &section_json);
     219         878 :         if (result < 0) {
     220           0 :                 goto failure;
     221             :         }
     222             : 
     223         878 :         return 0;
     224           0 : failure:
     225           0 :         json_free(&section_json);
     226           0 :         json_free(&subsection_json);
     227           0 :         return -1;
     228             : }
     229             : 
     230          16 : int add_section_to_json(struct traverse_state *state,
     231             :                         const char *key)
     232             : {
     233             :         struct json_object empty_json;
     234             :         int result;
     235             : 
     236          16 :         empty_json = json_new_object();
     237          16 :         if (json_is_invalid(&empty_json)) {
     238           0 :                 return -1;
     239             :         }
     240             : 
     241          16 :         result = json_add_object(&state->root_json, key, &empty_json);
     242          16 :         if (result < 0) {
     243           0 :                 return -1;
     244             :         }
     245             : 
     246          16 :         return result;
     247             : }
     248             : 
     249          16 : static int add_crypto_to_json(struct json_object *parent_json,
     250             :                               const char *key,
     251             :                               const char *cipher,
     252             :                               enum crypto_degree degree)
     253             : {
     254             :         struct json_object sub_json;
     255             :         const char *degree_str;
     256             :         int result;
     257             : 
     258          16 :         if (degree == CRYPTO_DEGREE_NONE) {
     259          12 :                 degree_str = "none";
     260           4 :         } else if (degree == CRYPTO_DEGREE_PARTIAL) {
     261           4 :                 degree_str = "partial";
     262             :         } else {
     263           0 :                 degree_str = "full";
     264             :         }
     265             : 
     266          16 :         sub_json = json_new_object();
     267          16 :         if (json_is_invalid(&sub_json)) {
     268           0 :                 goto failure;
     269             :         }
     270             : 
     271          16 :         result = json_add_string(&sub_json, "cipher", cipher);
     272          16 :         if (result < 0) {
     273           0 :                 goto failure;
     274             :         }
     275          16 :         result = json_add_string(&sub_json, "degree", degree_str);
     276          16 :         if (result < 0) {
     277           0 :                 goto failure;
     278             :         }
     279          16 :         result = json_add_object(parent_json, key, &sub_json);
     280          16 :         if (result < 0) {
     281           0 :                 goto failure;
     282             :         }
     283             : 
     284          16 :         return 0;
     285           0 : failure:
     286           0 :         json_free(&sub_json);
     287           0 :         return -1;
     288             : }
     289             : 
     290           4 : int traverse_connections_json(struct traverse_state *state,
     291             :                               const struct connections_data *crec,
     292             :                               const char *encryption_cipher,
     293             :                               enum crypto_degree encryption_degree,
     294             :                               const char *signing_cipher,
     295             :                               enum crypto_degree signing_degree)
     296             : {
     297             :         struct json_object sub_json;
     298             :         struct json_object connections_json;
     299             :         struct timeval tv;
     300             :         struct timeval_buf tv_buf;
     301           4 :         char *time = NULL;
     302           4 :         int result = 0;
     303           4 :         char *sess_id_str = NULL;
     304           4 :         char *tcon_id_str = NULL;
     305             : 
     306           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     307           4 :         if (tmp_ctx == NULL) {
     308           0 :                 return -1;
     309             :         }
     310             : 
     311           4 :         sub_json = json_new_object();
     312           4 :         if (json_is_invalid(&sub_json)) {
     313           0 :                 goto failure;
     314             :         }
     315           4 :         connections_json = json_get_object(&state->root_json, "tcons");
     316           4 :         if (json_is_invalid(&connections_json)) {
     317           0 :                 goto failure;
     318             :         }
     319             : 
     320           4 :         result = json_add_string(&sub_json, "service", crec->servicename);
     321           4 :         if (result < 0) {
     322           0 :                 goto failure;
     323             :         }
     324           4 :         result = add_server_id_to_json(&sub_json, crec->pid);
     325           4 :         if (result < 0) {
     326           0 :                 goto failure;
     327             :         }
     328           4 :         tcon_id_str = talloc_asprintf(tmp_ctx, "%u", crec->cnum);
     329           4 :         if (tcon_id_str == NULL) {
     330           0 :                 goto failure;
     331             :         }
     332           4 :         result = json_add_string(&sub_json, "tcon_id", tcon_id_str);
     333           4 :         if (result < 0) {
     334           0 :                 goto failure;
     335             :         }
     336           4 :         sess_id_str = talloc_asprintf(tmp_ctx, "%u", crec->sess_id);
     337           4 :         if (sess_id_str == NULL) {
     338           0 :                 goto failure;
     339             :         }
     340           4 :         result = json_add_string(&sub_json, "session_id", sess_id_str);
     341           4 :         if (result < 0) {
     342           0 :                 goto failure;
     343             :         }
     344           4 :         result = json_add_string(&sub_json, "machine", crec->machine);
     345           4 :         if (result < 0) {
     346           0 :                 goto failure;
     347             :         }
     348           4 :         nttime_to_timeval(&tv, crec->start);
     349           4 :         time = timeval_str_buf(&tv, true, true, &tv_buf);
     350           4 :         if (time == NULL) {
     351           0 :                 goto failure;
     352             :         }
     353           4 :         result = json_add_string(&sub_json, "connected_at", time);
     354           4 :         if (result < 0) {
     355           0 :                 goto failure;
     356             :         }
     357           4 :         result = add_crypto_to_json(&sub_json, "encryption",
     358             :                                    encryption_cipher, encryption_degree);
     359           4 :         if (result < 0) {
     360           0 :                 goto failure;
     361             :         }
     362           4 :         result = add_crypto_to_json(&sub_json, "signing",
     363             :                                    signing_cipher, signing_degree);
     364           4 :         if (result < 0) {
     365           0 :                 goto failure;
     366             :         }
     367             : 
     368           4 :         result = json_add_object(&connections_json, tcon_id_str, &sub_json);
     369           4 :         if (result < 0) {
     370           0 :                 goto failure;
     371             :         }
     372             : 
     373           4 :         result = json_update_object(&state->root_json, "tcons", &connections_json);
     374           4 :         if (result < 0) {
     375           0 :                 goto failure;
     376             :         }
     377             : 
     378           4 :         TALLOC_FREE(tmp_ctx);
     379           4 :         return 0;
     380           0 : failure:
     381           0 :         json_free(&sub_json);
     382           0 :         TALLOC_FREE(tmp_ctx);
     383           0 :         return -1;
     384             : }
     385             : 
     386           4 : int traverse_sessionid_json(struct traverse_state *state,
     387             :                             struct sessionid *session,
     388             :                             char *uid_str,
     389             :                             char *gid_str,
     390             :                             const char *encryption_cipher,
     391             :                             enum crypto_degree encryption_degree,
     392             :                             const char *signing_cipher,
     393             :                             enum crypto_degree signing_degree,
     394             :                             const char *connection_dialect)
     395             : {
     396             :         struct json_object sub_json;
     397             :         struct json_object session_json;
     398           4 :         int result = 0;
     399           4 :         char *id_str = NULL;
     400             : 
     401           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     402           4 :         if (tmp_ctx == NULL) {
     403           0 :                 return -1;
     404             :         }
     405             : 
     406           4 :         sub_json = json_new_object();
     407           4 :         if (json_is_invalid(&sub_json)) {
     408           0 :                 goto failure;
     409             :         }
     410             : 
     411           4 :         session_json = json_get_object(&state->root_json, "sessions");
     412           4 :         if (json_is_invalid(&session_json)) {
     413           0 :                 goto failure;
     414             :         }
     415             : 
     416           4 :         id_str = talloc_asprintf(tmp_ctx, "%u", session->id_num);
     417           4 :         result = json_add_string(&sub_json, "session_id", id_str);
     418           4 :         if (result < 0) {
     419           0 :                 goto failure;
     420             :         }
     421           4 :         result = add_server_id_to_json(&sub_json, session->pid);
     422           4 :         if (result < 0) {
     423           0 :                 goto failure;
     424             :         }
     425           4 :         result = json_add_int(&sub_json, "uid", session->uid);
     426           4 :         if (result < 0) {
     427           0 :                 goto failure;
     428             :         }
     429           4 :         result = json_add_int(&sub_json, "gid", session->gid);
     430           4 :         if (result < 0) {
     431           0 :                 goto failure;
     432             :         }
     433           4 :         result = json_add_string(&sub_json, "username", uid_str);
     434           4 :         if (result < 0) {
     435           0 :                 goto failure;
     436             :         }
     437           4 :         result = json_add_string(&sub_json, "groupname", gid_str);
     438           4 :         if (result < 0) {
     439           0 :                 goto failure;
     440             :         }
     441           4 :         result = json_add_string(&sub_json, "remote_machine", session->remote_machine);
     442           4 :         if (result < 0) {
     443           0 :                 goto failure;
     444             :         }
     445           4 :         result = json_add_string(&sub_json, "hostname", session->hostname);
     446           4 :         if (result < 0) {
     447           0 :                 goto failure;
     448             :         }
     449           4 :         result = json_add_string(&sub_json, "session_dialect", connection_dialect);
     450           4 :         if (result < 0) {
     451           0 :                 goto failure;
     452             :         }
     453           4 :         result = add_crypto_to_json(&sub_json, "encryption",
     454             :                                     encryption_cipher, encryption_degree);
     455           4 :         if (result < 0) {
     456           0 :                 goto failure;
     457             :         }
     458           4 :         result = add_crypto_to_json(&sub_json, "signing",
     459             :                                     signing_cipher, signing_degree);
     460           4 :         if (result < 0) {
     461           0 :                 goto failure;
     462             :         }
     463             : 
     464           4 :         result = json_add_object(&session_json, id_str, &sub_json);
     465           4 :         if (result < 0) {
     466           0 :                 goto failure;
     467             :         }
     468             : 
     469           4 :         result = json_update_object(&state->root_json, "sessions", &session_json);
     470           4 :         if (result < 0) {
     471           0 :                 goto failure;
     472             :         }
     473             : 
     474           4 :         TALLOC_FREE(tmp_ctx);
     475           4 :         return 0;
     476           0 : failure:
     477           0 :         json_free(&sub_json);
     478           0 :         TALLOC_FREE(tmp_ctx);
     479           0 :         return -1;
     480             : }
     481             : 
     482           4 : static int add_access_mode_to_json(struct json_object *parent_json,
     483             :                                    int access_int)
     484             : {
     485             :         struct json_object access_json;
     486           4 :         char *access_hex = NULL;
     487           4 :         const char *access_str = NULL;
     488             :         int result;
     489             : 
     490           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     491           4 :         if (tmp_ctx == NULL) {
     492           0 :                 return -1;
     493             :         }
     494             : 
     495           4 :         access_json = json_new_object();
     496           4 :         if (json_is_invalid(&access_json)) {
     497           0 :                 goto failure;
     498             :         }
     499             : 
     500           4 :         access_hex = talloc_asprintf(tmp_ctx, "0x%08x", access_int);
     501           4 :         result = json_add_string(&access_json, "hex", access_hex);
     502           4 :         if (result < 0) {
     503           0 :                   goto failure;
     504             :         }
     505           4 :         result = map_mask_to_json(&access_json, access_int, access_mask);
     506           4 :         if (result < 0) {
     507           0 :                 goto failure;
     508             :         }
     509             : 
     510           8 :         access_str = talloc_asprintf(tmp_ctx, "%s%s",
     511           4 :                                      (access_int & FILE_READ_DATA)?"R":"",
     512           4 :                                      (access_int & (FILE_WRITE_DATA|FILE_APPEND_DATA))?"W":"");
     513           4 :         result = json_add_string(&access_json, "text", access_str);
     514           4 :         if (result < 0) {
     515           0 :                   goto failure;
     516             :         }
     517             : 
     518           4 :         result = json_add_object(parent_json, "access_mask", &access_json);
     519           4 :         if (result < 0) {
     520           0 :                 goto failure;
     521             :         }
     522             : 
     523           4 :         TALLOC_FREE(tmp_ctx);
     524           4 :         return 0;
     525           0 : failure:
     526           0 :         json_free(&access_json);
     527           0 :         TALLOC_FREE(tmp_ctx);
     528           0 :         return -1;
     529             : }
     530             : 
     531           4 : static int add_caching_to_json(struct json_object *parent_json,
     532             :                               int op_type,
     533             :                               int lease_type)
     534             : {
     535             :         struct json_object caching_json;
     536           4 :         char *hex = NULL;
     537           4 :         char *caching_text = NULL;
     538           4 :         int caching_type = 0;
     539             :         int result;
     540             : 
     541           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     542           4 :         if (tmp_ctx == NULL) {
     543           0 :                 return -1;
     544             :         }
     545             : 
     546           4 :         caching_json = json_new_object();
     547           4 :         if (json_is_invalid(&caching_json)) {
     548           0 :                 goto failure;
     549             :         }
     550             : 
     551           4 :         if (op_type & LEASE_OPLOCK) {
     552           0 :                 caching_type = lease_type;
     553             :         } else {
     554           4 :                 if (op_type & LEVEL_II_OPLOCK) {
     555           0 :                         caching_type = SMB2_LEASE_READ;
     556           4 :                 } else if (op_type & EXCLUSIVE_OPLOCK) {
     557           0 :                         caching_type = SMB2_LEASE_READ + SMB2_LEASE_WRITE;
     558           4 :                 } else if (op_type & BATCH_OPLOCK) {
     559           0 :                         caching_type = SMB2_LEASE_READ + SMB2_LEASE_WRITE + SMB2_LEASE_HANDLE;
     560             :                 }
     561             :         }
     562           4 :         result = map_mask_to_json(&caching_json, caching_type, lease_mask);
     563           4 :         if (result < 0) {
     564           0 :                 goto failure;
     565             :         }
     566             : 
     567           4 :         hex = talloc_asprintf(tmp_ctx, "0x%08x", caching_type);
     568           4 :         if (hex == NULL) {
     569           0 :                 goto failure;
     570             :         }
     571           4 :         result = json_add_string(&caching_json, "hex", hex);
     572           4 :         if (result < 0) {
     573           0 :                 goto failure;
     574             :         }
     575             : 
     576          12 :         caching_text = talloc_asprintf(tmp_ctx, "%s%s%s",
     577           4 :                                        (caching_type & SMB2_LEASE_READ)?"R":"",
     578           4 :                                        (caching_type & SMB2_LEASE_WRITE)?"W":"",
     579           4 :                                        (caching_type & SMB2_LEASE_HANDLE)?"H":"");
     580           4 :         if (caching_text == NULL) {
     581           0 :                 return -1;
     582             :         }
     583             : 
     584           4 :         result = json_add_string(&caching_json, "text", caching_text);
     585           4 :         if (result < 0) {
     586           0 :                 goto failure;
     587             :         }
     588             : 
     589           4 :         result = json_add_object(parent_json, "caching", &caching_json);
     590           4 :         if (result < 0) {
     591           0 :                 goto failure;
     592             :         }
     593             : 
     594           4 :         TALLOC_FREE(tmp_ctx);
     595           4 :         return 0;
     596           0 : failure:
     597           0 :         json_free(&caching_json);
     598           0 :         TALLOC_FREE(tmp_ctx);
     599           0 :         return -1;
     600             : }
     601             : 
     602           4 : static int add_oplock_to_json(struct json_object *parent_json,
     603             :                               uint16_t op_type,
     604             :                               const char *op_str)
     605             : {
     606             :         struct json_object oplock_json;
     607             :         int result;
     608             : 
     609           4 :         oplock_json = json_new_object();
     610           4 :         if (json_is_invalid(&oplock_json)) {
     611           0 :                 goto failure;
     612             :         }
     613             : 
     614           4 :         if (op_type != 0) {
     615           0 :                 result = map_mask_to_json(&oplock_json, op_type, oplock_mask);
     616           0 :                 if (result < 0) {
     617           0 :                         goto failure;
     618             :                 }
     619           0 :                 result = json_add_string(&oplock_json, "text", op_str);
     620           0 :                 if (result < 0) {
     621           0 :                         goto failure;
     622             :                 }
     623             :         }
     624             : 
     625           4 :         result = json_add_object(parent_json, "oplock", &oplock_json);
     626           4 :         if (result < 0) {
     627           0 :                 goto failure;
     628             :         }
     629             : 
     630           4 :         return 0;
     631           0 : failure:
     632           0 :         json_free(&oplock_json);
     633           0 :         return -1;
     634             : }
     635             : 
     636           0 : static int lease_key_to_str(struct smb2_lease_key lease_key,
     637             :                             char *lease_str)
     638             : {
     639           0 :         uint8_t _buf[16] = {0};
     640           0 :         DATA_BLOB blob = data_blob_const(_buf, sizeof(_buf));
     641             :         struct GUID guid;
     642             :         NTSTATUS status;
     643           0 :         char *tmp = NULL;
     644             : 
     645           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     646           0 :         if (tmp_ctx == NULL) {
     647           0 :                 return -1;
     648             :         }
     649             : 
     650           0 :         PUSH_LE_U64(_buf, 0, lease_key.data[0]);
     651           0 :         PUSH_LE_U64(_buf, 8, lease_key.data[1]);
     652             : 
     653           0 :         status = GUID_from_ndr_blob(&blob, &guid);
     654           0 :         if (!NT_STATUS_IS_OK(status)) {
     655           0 :                 goto failure;
     656             :         }
     657           0 :         tmp = GUID_string(tmp_ctx, &guid);
     658           0 :         if (tmp == NULL) {
     659           0 :                 goto failure;
     660             :         }
     661           0 :         fstrcpy(lease_str, tmp);
     662             : 
     663           0 :         TALLOC_FREE(tmp_ctx);
     664           0 :         return 0;
     665           0 : failure:
     666           0 :         TALLOC_FREE(tmp_ctx);
     667           0 :         return -1;
     668             : }
     669             : 
     670           4 : static int add_lease_to_json(struct json_object *parent_json,
     671             :                              int lease_type,
     672             :                              struct smb2_lease_key lease_key,
     673             :                              bool add_lease)
     674             : {
     675             :         struct json_object lease_json;
     676           4 :         char *lease_hex = NULL;
     677           4 :         char *lease_text = NULL;
     678             :         fstring lease_key_str;
     679             :         int result;
     680             : 
     681           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     682           4 :         if (tmp_ctx == NULL) {
     683           0 :                 return -1;
     684             :         }
     685             : 
     686           4 :         lease_json = json_new_object();
     687           4 :         if (json_is_invalid(&lease_json)) {
     688           0 :                 goto failure;
     689             :         }
     690             : 
     691             : 
     692           4 :         if (add_lease) {
     693           0 :                 result = lease_key_to_str(lease_key, lease_key_str);
     694           0 :                 if (result < 0) {
     695           0 :                         goto failure;
     696             :                 }
     697           0 :                 result = json_add_string(&lease_json, "lease_key", lease_key_str);
     698           0 :                 if (result < 0) {
     699           0 :                         goto failure;
     700             :                 }
     701           0 :                 lease_hex = talloc_asprintf(tmp_ctx, "0x%08x", lease_type);
     702           0 :                 result = json_add_string(&lease_json, "hex", lease_hex);
     703           0 :                 if (result < 0) {
     704           0 :                         goto failure;
     705             :                 }
     706           0 :                 if (lease_type > (SMB2_LEASE_WRITE + SMB2_LEASE_HANDLE + SMB2_LEASE_READ)) {
     707           0 :                         result = json_add_bool(&lease_json, "UNKNOWN", true);
     708           0 :                         if (result < 0) {
     709           0 :                                 goto failure;
     710             :                         }
     711             :                 } else {
     712           0 :                         result = map_mask_to_json(&lease_json, lease_type, lease_mask);
     713           0 :                         if (result < 0) {
     714           0 :                                 goto failure;
     715             :                         }
     716             :                 }
     717           0 :                 lease_text = talloc_asprintf(tmp_ctx, "%s%s%s",
     718           0 :                                              (lease_type & SMB2_LEASE_READ)?"R":"",
     719           0 :                                              (lease_type & SMB2_LEASE_WRITE)?"W":"",
     720           0 :                                              (lease_type & SMB2_LEASE_HANDLE)?"H":"");
     721             : 
     722           0 :                 result = json_add_string(&lease_json, "text", lease_text);
     723           0 :                 if (result < 0) {
     724           0 :                         goto failure;
     725             :                 }
     726             :         }
     727             : 
     728           4 :         result = json_add_object(parent_json, "lease", &lease_json);
     729           4 :         if (result < 0) {
     730           0 :                 goto failure;
     731             :         }
     732             : 
     733           4 :         TALLOC_FREE(tmp_ctx);
     734           4 :         return 0;
     735           0 : failure:
     736           0 :         json_free(&lease_json);
     737           0 :         TALLOC_FREE(tmp_ctx);
     738           0 :         return -1;
     739             : }
     740             : 
     741           4 : static int add_sharemode_to_json(struct json_object *parent_json,
     742             :                                  int sharemode)
     743             : {
     744             :         struct json_object sharemode_json;
     745           4 :         char *hex = NULL;
     746           4 :         char *text = NULL;
     747             :         int result;
     748             : 
     749           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     750           4 :         if (tmp_ctx == NULL) {
     751           0 :                 return -1;
     752             :         }
     753             : 
     754           4 :         sharemode_json = json_new_object();
     755           4 :         if (json_is_invalid(&sharemode_json)) {
     756           0 :                 goto failure;
     757             :         }
     758             : 
     759           4 :         hex = talloc_asprintf(tmp_ctx, "0x%08x", sharemode);
     760           4 :         if (hex == NULL) {
     761           0 :                 goto failure;
     762             :         }
     763           4 :         result = json_add_string(&sharemode_json, "hex", hex);
     764           4 :         if (result < 0) {
     765           0 :                 goto failure;
     766             :         }
     767           4 :         result = map_mask_to_json(&sharemode_json, sharemode, sharemode_mask);
     768           4 :         if (result < 0) {
     769           0 :                 goto failure;
     770             :         }
     771             : 
     772          12 :         text = talloc_asprintf(tmp_ctx, "%s%s%s",
     773           4 :                                (sharemode & FILE_SHARE_READ)?"R":"",
     774           4 :                                (sharemode & FILE_SHARE_WRITE)?"W":"",
     775           4 :                                (sharemode & FILE_SHARE_DELETE)?"D":"");
     776           4 :         if (text == NULL) {
     777           0 :                 goto failure;
     778             :         }
     779           4 :         result = json_add_string(&sharemode_json, "text", text);
     780           4 :         if (result < 0) {
     781           0 :                 goto failure;
     782             :         }
     783             : 
     784           4 :         result = json_add_object(parent_json, "sharemode", &sharemode_json);
     785           4 :         if (result < 0) {
     786           0 :                 goto failure;
     787             :         }
     788             : 
     789           4 :         TALLOC_FREE(tmp_ctx);
     790           4 :         return 0;
     791           0 : failure:
     792           0 :         json_free(&sharemode_json);
     793           0 :         TALLOC_FREE(tmp_ctx);
     794           0 :         return -1;
     795             : }
     796             : 
     797           4 : static int add_open_to_json(struct json_object *parent_json,
     798             :                             const struct share_mode_entry *e,
     799             :                             bool resolve_uids,
     800             :                             const char *op_str,
     801             :                             uint32_t lease_type,
     802             :                             const char *uid_str)
     803             : {
     804           4 :         struct json_object sub_json = {
     805             :                 .valid = false,
     806             :         };
     807           4 :         struct json_object opens_json = {
     808             :                 .valid = false,
     809             :         };
     810             :         struct timeval_buf tv_buf;
     811           4 :         int result = 0;
     812             :         char *timestr;
     813           4 :         bool add_lease = false;
     814           4 :         char *key = NULL;
     815           4 :         char *share_file_id = NULL;
     816           4 :         char *pid = NULL;
     817             :         struct server_id_buf tmp;
     818             : 
     819           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     820           4 :         if (tmp_ctx == NULL) {
     821           0 :                 return -1;
     822             :         }
     823             : 
     824           4 :         opens_json = json_get_object(parent_json, "opens");
     825           4 :         if (json_is_invalid(&opens_json)) {
     826           0 :                 goto failure;
     827             :         }
     828           4 :         sub_json = json_new_object();
     829           4 :         if (json_is_invalid(&sub_json)) {
     830           0 :                 goto failure;
     831             :         }
     832             : 
     833             : 
     834           4 :         result = add_server_id_to_json(&sub_json, e->pid);
     835           4 :         if (result < 0) {
     836           0 :                 goto failure;
     837             :         }
     838           4 :         if (resolve_uids) {
     839           0 :                 result = json_add_string(&sub_json, "username", uid_str);
     840           0 :                 if (result < 0) {
     841           0 :                         goto failure;
     842             :                 }
     843             :         }
     844           4 :         result = json_add_int(&sub_json, "uid", e->uid);
     845           4 :         if (result < 0) {
     846           0 :                 goto failure;
     847             :         }
     848           4 :         share_file_id = talloc_asprintf(tmp_ctx, "%"PRIu64, e->share_file_id);
     849           4 :         result = json_add_string(&sub_json, "share_file_id", share_file_id);
     850           4 :         if (result < 0) {
     851           0 :                 goto failure;
     852             :         }
     853           4 :         result = add_sharemode_to_json(&sub_json, e->share_access);
     854           4 :         if (result < 0) {
     855           0 :                 goto failure;
     856             :         }
     857           4 :         result = add_access_mode_to_json(&sub_json, e->access_mask);
     858           4 :         if (result < 0) {
     859           0 :                 goto failure;
     860             :         }
     861           4 :         result = add_caching_to_json(&sub_json, e->op_type, lease_type);
     862           4 :         if (result < 0) {
     863           0 :                 goto failure;
     864             :         }
     865           4 :         result = add_oplock_to_json(&sub_json, e->op_type, op_str);
     866           4 :         if (result < 0) {
     867           0 :                 goto failure;
     868             :         }
     869           4 :         add_lease = e->op_type & LEASE_OPLOCK;
     870           4 :         result = add_lease_to_json(&sub_json, lease_type, e->lease_key, add_lease);
     871           4 :         if (result < 0) {
     872           0 :                 goto failure;
     873             :         }
     874             : 
     875           4 :         timestr = timeval_str_buf(&e->time, true, true, &tv_buf);
     876           4 :         if (timestr == NULL) {
     877           0 :                 goto failure;
     878             :         }
     879           4 :         result = json_add_string(&sub_json, "opened_at", timestr);
     880           4 :         if (result < 0) {
     881           0 :                 goto failure;
     882             :         }
     883             : 
     884           4 :         pid = server_id_str_buf(e->pid, &tmp);
     885           4 :         key = talloc_asprintf(tmp_ctx, "%s/%"PRIu64, pid, e->share_file_id);
     886           4 :         result = json_add_object(&opens_json, key, &sub_json);
     887           4 :         if (result < 0) {
     888           0 :                 goto failure;
     889             :         }
     890           4 :         result = json_update_object(parent_json, "opens", &opens_json);
     891           4 :         if (result < 0) {
     892           0 :                 goto failure;
     893             :         }
     894             : 
     895           4 :         TALLOC_FREE(tmp_ctx);
     896           4 :         return 0;
     897           0 : failure:
     898           0 :         json_free(&opens_json);
     899           0 :         json_free(&sub_json);
     900           0 :         TALLOC_FREE(tmp_ctx);
     901           0 :         return -1;
     902             : }
     903             : 
     904           4 : static int add_fileid_to_json(struct json_object *parent_json,
     905             :                               struct file_id fid)
     906             : {
     907             :         struct json_object fid_json;
     908             :         int result;
     909             : 
     910           4 :         fid_json = json_new_object();
     911           4 :         if (json_is_invalid(&fid_json)) {
     912           0 :                 goto failure;
     913             :         }
     914             : 
     915           4 :         result = json_add_int(&fid_json, "devid", fid.devid);
     916           4 :         if (result < 0) {
     917           0 :                 goto failure;
     918             :         }
     919           4 :         result = json_add_int(&fid_json, "inode", fid.inode);
     920           4 :         if (result < 0) {
     921           0 :                 goto failure;
     922             :         }
     923           4 :         result = json_add_int(&fid_json, "extid", fid.extid);
     924           4 :         if (result < 0) {
     925           0 :                 goto failure;
     926             :         }
     927             : 
     928           4 :         result = json_add_object(parent_json, "fileid", &fid_json);
     929           4 :         if (result < 0) {
     930           0 :                 goto failure;
     931             :         }
     932             : 
     933           4 :         return 0;
     934           0 : failure:
     935           0 :         json_free(&fid_json);
     936           0 :         return -1;
     937             : }
     938             : 
     939           4 : int print_share_mode_json(struct traverse_state *state,
     940             :                           const struct share_mode_data *d,
     941             :                           const struct share_mode_entry *e,
     942             :                           struct file_id fid,
     943             :                           const char *uid_str,
     944             :                           const char *op_str,
     945             :                           uint32_t lease_type,
     946             :                           const char *filename)
     947             : {
     948           4 :         struct json_object locks_json = {
     949             :                 .valid = false,
     950             :         };
     951           4 :         struct json_object file_json = {
     952             :                 .valid = false,
     953             :         };
     954           4 :         char *key = NULL;
     955           4 :         int result = 0;
     956             : 
     957           4 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     958           4 :         if (tmp_ctx == NULL) {
     959           0 :                 return -1;
     960             :         }
     961             : 
     962           4 :         if (d->servicepath[strlen(d->servicepath)-1] == '/') {
     963           0 :                 key = talloc_asprintf(tmp_ctx, "%s%s", d->servicepath, filename);
     964             :         } else {
     965           4 :                 key = talloc_asprintf(tmp_ctx, "%s/%s", d->servicepath, filename);
     966             :         }
     967             : 
     968           4 :         locks_json = json_get_object(&state->root_json, "open_files");
     969           4 :         if (json_is_invalid(&locks_json)) {
     970           0 :                 goto failure;
     971             :         }
     972           4 :         file_json = json_get_object(&locks_json, key);
     973           4 :         if (json_is_invalid(&file_json)) {
     974           0 :                 goto failure;
     975             :         }
     976             : 
     977           4 :         result = json_add_string(&file_json, "service_path", d->servicepath);
     978           4 :         if (result < 0) {
     979           0 :                 goto failure;
     980             :         }
     981           4 :         result = json_add_string(&file_json, "filename", filename);
     982           4 :         if (result < 0) {
     983           0 :                 goto failure;
     984             :         }
     985           4 :         result = add_fileid_to_json(&file_json, fid);
     986           4 :         if (result < 0) {
     987           0 :                 goto failure;
     988             :         }
     989           4 :         result = json_add_int(&file_json, "num_pending_deletes", d->num_delete_tokens);
     990           4 :         if (result < 0) {
     991           0 :                 goto failure;
     992             :         }
     993             : 
     994           4 :         result = add_open_to_json(&file_json,
     995             :                                   e,
     996           4 :                                   state->resolve_uids,
     997             :                                   op_str,
     998             :                                   lease_type,
     999             :                                   uid_str);
    1000           4 :         if (result < 0) {
    1001           0 :                 goto failure;
    1002             :         }
    1003             : 
    1004           4 :         result = json_update_object(&locks_json, key, &file_json);
    1005           4 :         if (result < 0) {
    1006           0 :                 goto failure;
    1007             :         }
    1008           4 :         result = json_update_object(&state->root_json, "open_files", &locks_json);
    1009           4 :         if (result < 0) {
    1010           0 :                 goto failure;
    1011             :         }
    1012             : 
    1013           4 :         TALLOC_FREE(tmp_ctx);
    1014           4 :         return 0;
    1015           0 : failure:
    1016           0 :         json_free(&file_json);
    1017           0 :         json_free(&locks_json);
    1018           0 :         TALLOC_FREE(tmp_ctx);
    1019           0 :         return -1;
    1020             : }
    1021             : 
    1022           0 : static int add_lock_to_json(struct json_object *parent_json,
    1023             :                             struct server_id server_id,
    1024             :                             const char *type,
    1025             :                             enum brl_flavour flavour,
    1026             :                             intmax_t start,
    1027             :                             intmax_t size)
    1028             : {
    1029           0 :         struct json_object sub_json = {
    1030             :                 .valid = false,
    1031             :         };
    1032           0 :         struct json_object locks_json = {
    1033             :                 .valid = false,
    1034             :         };
    1035             :         const char *flavour_str;
    1036           0 :         int result = 0;
    1037             : 
    1038           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
    1039           0 :         if (tmp_ctx == NULL) {
    1040           0 :                 return -1;
    1041             :         }
    1042             : 
    1043           0 :         locks_json = json_get_array(parent_json, "locks");
    1044           0 :         if (json_is_invalid(&locks_json)) {
    1045           0 :                 goto failure;
    1046             :         }
    1047           0 :         sub_json = json_new_object();
    1048           0 :         if (json_is_invalid(&sub_json)) {
    1049           0 :                 goto failure;
    1050             :         }
    1051             : 
    1052           0 :         result = add_server_id_to_json(&sub_json, server_id);
    1053           0 :         if (result < 0) {
    1054           0 :                 goto failure;
    1055             :         }
    1056           0 :         result = json_add_string(&sub_json, "type", type);
    1057           0 :         if (result < 0) {
    1058           0 :                 goto failure;
    1059             :         }
    1060           0 :         flavour_str = talloc_asprintf(tmp_ctx, "%s%s",
    1061             :                                       (flavour == WINDOWS_LOCK)?"Windows":"",
    1062             :                                       (flavour == POSIX_LOCK)?"Posix":"");
    1063           0 :         result = json_add_string(&sub_json, "flavour", flavour_str);
    1064           0 :         if (result < 0) {
    1065           0 :                 goto failure;
    1066             :         }
    1067           0 :         result = json_add_int(&sub_json, "start", start);
    1068           0 :         if (result < 0) {
    1069           0 :                 goto failure;
    1070             :         }
    1071           0 :         result = json_add_int(&sub_json, "size", size);
    1072           0 :         if (result < 0) {
    1073           0 :                 goto failure;
    1074             :         }
    1075             : 
    1076           0 :         result = json_add_object(&locks_json, NULL, &sub_json);
    1077           0 :         if (result < 0) {
    1078           0 :                 goto failure;
    1079             :         }
    1080           0 :         result = json_update_object(parent_json, "locks", &locks_json);
    1081           0 :         if (result < 0) {
    1082           0 :                 goto failure;
    1083             :         }
    1084             : 
    1085           0 :         TALLOC_FREE(tmp_ctx);
    1086           0 :         return 0;
    1087           0 : failure:
    1088           0 :         json_free(&locks_json);
    1089           0 :         json_free(&sub_json);
    1090           0 :         TALLOC_FREE(tmp_ctx);
    1091           0 :         return -1;
    1092             : }
    1093             : 
    1094           0 : int print_brl_json(struct traverse_state *state,
    1095             :                    const struct server_id server_id,
    1096             :                    struct file_id fid,
    1097             :                    const char *type,
    1098             :                    enum brl_flavour flavour,
    1099             :                    intmax_t start,
    1100             :                    intmax_t size,
    1101             :                    const char *sharepath,
    1102             :                    const char *filename)
    1103             : {
    1104           0 :         struct json_object file_json = {
    1105             :                 .valid = false,
    1106             :         };
    1107           0 :         struct json_object brl_json = {
    1108             :                 .valid = false,
    1109             :         };
    1110           0 :         int result = 0;
    1111             :         char *key;
    1112             : 
    1113           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
    1114           0 :         if (tmp_ctx == NULL) {
    1115           0 :                 return -1;
    1116             :         }
    1117             : 
    1118           0 :         if (sharepath[strlen(sharepath)-1] == '/') {
    1119           0 :                 key = talloc_asprintf(tmp_ctx, "%s%s", sharepath, filename);
    1120             :         } else {
    1121           0 :                 key = talloc_asprintf(tmp_ctx, "%s/%s", sharepath, filename);
    1122             :         }
    1123           0 :         if (key == NULL) {
    1124           0 :                 goto failure;
    1125             :         }
    1126             : 
    1127           0 :         brl_json = json_get_object(&state->root_json, "byte_range_locks");
    1128           0 :         if (json_is_invalid(&brl_json)) {
    1129           0 :                 goto failure;
    1130             :         }
    1131           0 :         file_json = json_get_object(&brl_json, key);
    1132           0 :         if (json_is_invalid(&file_json)) {
    1133           0 :                 goto failure;
    1134             :         }
    1135             : 
    1136           0 :         result = add_fileid_to_json(&file_json, fid);
    1137           0 :         if (result < 0) {
    1138           0 :                 goto failure;
    1139             :         }
    1140           0 :         result = json_add_string(&file_json, "file_name", filename);
    1141           0 :         if (result < 0) {
    1142           0 :                 goto failure;
    1143             :         }
    1144           0 :         result = json_add_string(&file_json, "share_path", sharepath);
    1145           0 :         if (result < 0) {
    1146           0 :                 goto failure;
    1147             :         }
    1148           0 :         result = add_server_id_to_json(&file_json, server_id);
    1149           0 :         if (result < 0) {
    1150           0 :                 goto failure;
    1151             :         }
    1152           0 :         result = add_lock_to_json(&file_json, server_id, type, flavour, start, size);
    1153           0 :         if (result < 0) {
    1154           0 :                 goto failure;
    1155             :         }
    1156             : 
    1157           0 :         result = json_add_object(&brl_json, key, &file_json);
    1158           0 :         if (result < 0) {
    1159           0 :                 goto failure;
    1160             :         }
    1161           0 :         result = json_update_object(&state->root_json, "byte_range_locks", &brl_json);
    1162           0 :         if (result < 0) {
    1163           0 :                 goto failure;
    1164             :          }
    1165             : 
    1166           0 :         TALLOC_FREE(tmp_ctx);
    1167           0 :         return 0;
    1168           0 : failure:
    1169           0 :         json_free(&file_json);
    1170           0 :         json_free(&brl_json);
    1171           0 :         TALLOC_FREE(tmp_ctx);
    1172           0 :         return -1;
    1173             : }
    1174             : 
    1175           0 : bool print_notify_rec_json(struct traverse_state *state,
    1176             :                            const struct notify_instance *instance,
    1177             :                            const struct server_id server_id,
    1178             :                            const char *path)
    1179             : {
    1180             :         struct json_object sub_json;
    1181             :         struct json_object notify_json;
    1182           0 :         char *filter = NULL;
    1183           0 :         char *subdir_filter = NULL;
    1184             :         struct timeval_buf tv_buf;
    1185             :         struct timeval val;
    1186           0 :         char *time = NULL;
    1187           0 :         char *pid = NULL;
    1188             :         struct server_id_buf tmp;
    1189           0 :         int result = 0;
    1190             : 
    1191           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
    1192           0 :         if (tmp_ctx == NULL) {
    1193           0 :                 return -1;
    1194             :         }
    1195             : 
    1196           0 :         sub_json = json_new_object();
    1197           0 :         if (json_is_invalid(&sub_json)) {
    1198           0 :                 return false;
    1199             :         }
    1200           0 :         notify_json = json_get_object(&state->root_json, "notifies");
    1201           0 :         if (json_is_invalid(&notify_json)) {
    1202           0 :                 goto failure;
    1203             :         }
    1204             : 
    1205           0 :         result = add_server_id_to_json(&sub_json, server_id);
    1206           0 :         if (result < 0) {
    1207           0 :                 goto failure;
    1208             :         }
    1209           0 :         result = json_add_string(&sub_json, "path", path);
    1210           0 :         if (result < 0) {
    1211           0 :                 goto failure;
    1212             :         }
    1213           0 :         filter = talloc_asprintf(tmp_ctx, "%u", instance->filter);
    1214           0 :         if (filter == NULL) {
    1215           0 :                 goto failure;
    1216             :         }
    1217           0 :         result = json_add_string(&sub_json, "filter", filter);
    1218           0 :         if (result < 0) {
    1219           0 :                 goto failure;
    1220             :         }
    1221           0 :         subdir_filter = talloc_asprintf(tmp_ctx, "%u", instance->subdir_filter);
    1222           0 :         if (subdir_filter == NULL) {
    1223           0 :                 goto failure;
    1224             :         }
    1225           0 :         result = json_add_string(&sub_json, "subdir_filter", subdir_filter);
    1226           0 :         if (result < 0) {
    1227           0 :                 goto failure;
    1228             :         }
    1229           0 :         val = convert_timespec_to_timeval(instance->creation_time);
    1230           0 :         time = timeval_str_buf(&val, true, true, &tv_buf);
    1231           0 :         result = json_add_string(&sub_json, "creation_time", time);
    1232           0 :         if (result < 0) {
    1233           0 :                 goto failure;
    1234             :         }
    1235             : 
    1236           0 :         pid = server_id_str_buf(server_id, &tmp);
    1237           0 :         result = json_add_object(&notify_json, pid, &sub_json);
    1238           0 :         if (result < 0) {
    1239           0 :                 goto failure;
    1240             :         }
    1241             : 
    1242           0 :         result = json_update_object(&state->root_json, "notifies", &notify_json);
    1243           0 :         if (result < 0) {
    1244           0 :                 goto failure;
    1245             :         }
    1246             : 
    1247           0 :         TALLOC_FREE(tmp_ctx);
    1248           0 :         return true;
    1249           0 : failure:
    1250           0 :         json_free(&sub_json);
    1251           0 :         TALLOC_FREE(tmp_ctx);
    1252           0 :         return false;
    1253             : }

Generated by: LCOV version 1.14