smbstatus: add a basic dictionary with open files
[Samba.git] / source3 / utils / status_json.c
bloba11024e7d4b32c8a1025c2639435dacc301baffc
1 /*
2 * Samba Unix/Linux SMB client library
3 * Json output
4 * Copyright (C) Jule Anger 2022
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.
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.
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/>.
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"
31 #include <jansson.h>
32 #include "audit_logging.h" /* various JSON helpers */
33 #include "auth/common_auth.h"
35 int add_general_information_to_json(struct traverse_state *state)
37 int result;
39 result = json_add_timestamp(&state->root_json);
40 if (result < 0) {
41 return -1;
44 result = json_add_string(&state->root_json, "version", samba_version_string());
45 if (result < 0) {
46 return -1;
49 result = json_add_string(&state->root_json, "smb_conf", get_dyn_CONFIGFILE());
50 if (result < 0) {
51 return -1;
54 return 0;
57 static int add_server_id_to_json(struct json_object *parent_json,
58 const struct server_id server_id)
60 struct json_object sub_json;
61 char *pid_str = NULL;
62 char *task_id_str = NULL;
63 char *vnn_str = NULL;
64 char *unique_id_str = NULL;
65 int result;
67 TALLOC_CTX *tmp_ctx = talloc_stackframe();
68 if (tmp_ctx == NULL) {
69 return -1;
72 sub_json = json_new_object();
73 if (json_is_invalid(&sub_json)) {
74 goto failure;
77 pid_str = talloc_asprintf(tmp_ctx, "%lu", server_id.pid);
78 result = json_add_string(&sub_json, "pid", pid_str);
79 if (result < 0) {
80 goto failure;
82 task_id_str = talloc_asprintf(tmp_ctx, "%u", server_id.task_id);
83 result = json_add_string(&sub_json, "task_id", task_id_str);
84 if (result < 0) {
85 goto failure;
87 vnn_str = talloc_asprintf(tmp_ctx, "%u", server_id.vnn);
88 result = json_add_string(&sub_json, "vnn", vnn_str);
89 if (result < 0) {
90 goto failure;
92 unique_id_str = talloc_asprintf(tmp_ctx, "%lu", server_id.unique_id);
93 result = json_add_string(&sub_json, "unique_id", unique_id_str);
94 if (result < 0) {
95 goto failure;
98 result = json_add_object(parent_json, "server_id", &sub_json);
99 if (result < 0) {
100 goto failure;
103 TALLOC_FREE(tmp_ctx);
104 return 0;
105 failure:
106 json_free(&sub_json);
107 TALLOC_FREE(tmp_ctx);
108 return -1;
111 int add_section_to_json(struct traverse_state *state,
112 const char *key)
114 struct json_object empty_json;
115 int result;
117 empty_json = json_new_object();
118 if (json_is_invalid(&empty_json)) {
119 return -1;
122 result = json_add_object(&state->root_json, key, &empty_json);
123 if (result < 0) {
124 return -1;
127 return result;
130 static int add_crypto_to_json(struct json_object *parent_json,
131 const char *key,
132 const char *cipher,
133 enum crypto_degree degree)
135 struct json_object sub_json;
136 const char *degree_str;
137 int result;
139 if (degree == CRYPTO_DEGREE_NONE) {
140 degree_str = "none";
141 } else if (degree == CRYPTO_DEGREE_PARTIAL) {
142 degree_str = "partial";
143 } else {
144 degree_str = "full";
147 sub_json = json_new_object();
148 if (json_is_invalid(&sub_json)) {
149 goto failure;
152 result = json_add_string(&sub_json, "cipher", cipher);
153 if (result < 0) {
154 goto failure;
156 result = json_add_string(&sub_json, "degree", degree_str);
157 if (result < 0) {
158 goto failure;
160 result = json_add_object(parent_json, key, &sub_json);
161 if (result < 0) {
162 goto failure;
165 return 0;
166 failure:
167 json_free(&sub_json);
168 return -1;
171 int traverse_connections_json(struct traverse_state *state,
172 const struct connections_data *crec,
173 const char *encryption_cipher,
174 enum crypto_degree encryption_degree,
175 const char *signing_cipher,
176 enum crypto_degree signing_degree)
178 struct json_object sub_json;
179 struct json_object connections_json;
180 struct timeval tv;
181 struct timeval_buf tv_buf;
182 char *time = NULL;
183 int result = 0;
184 char *sess_id_str = NULL;
185 char *tcon_id_str = NULL;
187 TALLOC_CTX *tmp_ctx = talloc_stackframe();
188 if (tmp_ctx == NULL) {
189 return -1;
192 sub_json = json_new_object();
193 if (json_is_invalid(&sub_json)) {
194 goto failure;
196 connections_json = json_get_object(&state->root_json, "tcons");
197 if (json_is_invalid(&connections_json)) {
198 goto failure;
201 result = json_add_string(&sub_json, "service", crec->servicename);
202 if (result < 0) {
203 goto failure;
205 result = add_server_id_to_json(&sub_json, crec->pid);
206 if (result < 0) {
207 goto failure;
209 tcon_id_str = talloc_asprintf(tmp_ctx, "%u", crec->cnum);
210 if (tcon_id_str == NULL) {
211 goto failure;
213 result = json_add_string(&sub_json, "tcon_id", tcon_id_str);
214 if (result < 0) {
215 goto failure;
217 sess_id_str = talloc_asprintf(tmp_ctx, "%u", crec->sess_id);
218 if (sess_id_str == NULL) {
219 goto failure;
221 result = json_add_string(&sub_json, "session_id", sess_id_str);
222 if (result < 0) {
223 goto failure;
225 result = json_add_string(&sub_json, "machine", crec->machine);
226 if (result < 0) {
227 goto failure;
229 nttime_to_timeval(&tv, crec->start);
230 time = timeval_str_buf(&tv, true, true, &tv_buf);
231 if (time == NULL) {
232 goto failure;
234 result = json_add_string(&sub_json, "connected_at", time);
235 if (result < 0) {
236 goto failure;
238 result = add_crypto_to_json(&sub_json, "encryption",
239 encryption_cipher, encryption_degree);
240 if (result < 0) {
241 goto failure;
243 result = add_crypto_to_json(&sub_json, "signing",
244 signing_cipher, signing_degree);
245 if (result < 0) {
246 goto failure;
249 result = json_add_object(&connections_json, tcon_id_str, &sub_json);
250 if (result < 0) {
251 goto failure;
254 result = json_update_object(&state->root_json, "tcons", &connections_json);
255 if (result < 0) {
256 goto failure;
259 TALLOC_FREE(tmp_ctx);
260 return 0;
261 failure:
262 json_free(&sub_json);
263 TALLOC_FREE(tmp_ctx);
264 return -1;
267 int traverse_sessionid_json(struct traverse_state *state,
268 struct sessionid *session,
269 char *uid_str,
270 char *gid_str,
271 const char *encryption_cipher,
272 enum crypto_degree encryption_degree,
273 const char *signing_cipher,
274 enum crypto_degree signing_degree,
275 const char *connection_dialect)
277 struct json_object sub_json;
278 struct json_object session_json;
279 int result = 0;
280 char *id_str = NULL;
282 TALLOC_CTX *tmp_ctx = talloc_stackframe();
283 if (tmp_ctx == NULL) {
284 return -1;
287 sub_json = json_new_object();
288 if (json_is_invalid(&sub_json)) {
289 goto failure;
292 session_json = json_get_object(&state->root_json, "sessions");
293 if (json_is_invalid(&session_json)) {
294 goto failure;
297 id_str = talloc_asprintf(tmp_ctx, "%u", session->id_num);
298 result = json_add_string(&sub_json, "session_id", id_str);
299 if (result < 0) {
300 goto failure;
302 result = add_server_id_to_json(&sub_json, session->pid);
303 if (result < 0) {
304 goto failure;
306 result = json_add_int(&sub_json, "uid", session->uid);
307 if (result < 0) {
308 goto failure;
310 result = json_add_int(&sub_json, "gid", session->gid);
311 if (result < 0) {
312 goto failure;
314 result = json_add_string(&sub_json, "username", uid_str);
315 if (result < 0) {
316 goto failure;
318 result = json_add_string(&sub_json, "groupname", gid_str);
319 if (result < 0) {
320 goto failure;
322 result = json_add_string(&sub_json, "remote_machine", session->remote_machine);
323 if (result < 0) {
324 goto failure;
326 result = json_add_string(&sub_json, "hostname", session->hostname);
327 if (result < 0) {
328 goto failure;
330 result = json_add_string(&sub_json, "session_dialect", connection_dialect);
331 if (result < 0) {
332 goto failure;
334 result = add_crypto_to_json(&sub_json, "encryption",
335 encryption_cipher, encryption_degree);
336 if (result < 0) {
337 goto failure;
339 result = add_crypto_to_json(&sub_json, "signing",
340 signing_cipher, signing_degree);
341 if (result < 0) {
342 goto failure;
345 result = json_add_object(&session_json, id_str, &sub_json);
346 if (result < 0) {
347 goto failure;
350 result = json_update_object(&state->root_json, "sessions", &session_json);
351 if (result < 0) {
352 goto failure;
355 TALLOC_FREE(tmp_ctx);
356 return 0;
357 failure:
358 json_free(&sub_json);
359 TALLOC_FREE(tmp_ctx);
360 return -1;
363 int print_share_mode_json(struct traverse_state *state,
364 const struct share_mode_data *d,
365 const char *filename)
367 struct json_object locks_json;
368 struct json_object file_json;
369 char *key = NULL;
370 int result = 0;
372 TALLOC_CTX *tmp_ctx = talloc_stackframe();
373 if (tmp_ctx == NULL) {
374 return -1;
377 if (d->servicepath[strlen(d->servicepath)-1] == '/') {
378 key = talloc_asprintf(tmp_ctx, "%s%s", d->servicepath, filename);
379 } else {
380 key = talloc_asprintf(tmp_ctx, "%s/%s", d->servicepath, filename);
383 locks_json = json_get_object(&state->root_json, "open_files");
384 if (json_is_invalid(&locks_json)) {
385 goto failure;
387 file_json = json_get_object(&locks_json, key);
388 if (json_is_invalid(&file_json)) {
389 goto failure;
392 result = json_add_string(&file_json, "service_path", d->servicepath);
393 if (result < 0) {
394 goto failure;
396 result = json_add_string(&file_json, "filename", filename);
397 if (result < 0) {
398 goto failure;
400 result = json_add_int(&file_json, "num_pending_deletes", d->num_delete_tokens);
401 if (result < 0) {
402 goto failure;
405 result = json_update_object(&locks_json, key, &file_json);
406 if (result < 0) {
407 goto failure;
409 result = json_update_object(&state->root_json, "open_files", &locks_json);
410 if (result < 0) {
411 goto failure;
414 TALLOC_FREE(tmp_ctx);
415 return 0;
416 failure:
417 json_free(&file_json);
418 json_free(&locks_json);
419 TALLOC_FREE(tmp_ctx);
420 return -1;