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