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(§ion_json)) {
202 0 : goto failure;
203 : }
204 878 : subsection_json = json_get_object(§ion_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(§ion_json, subsection, &subsection_json);
215 878 : if (result < 0) {
216 0 : goto failure;
217 : }
218 878 : result = json_update_object(&state->root_json, section, §ion_json);
219 878 : if (result < 0) {
220 0 : goto failure;
221 : }
222 :
223 878 : return 0;
224 0 : failure:
225 0 : json_free(§ion_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(¬ify_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(¬ify_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", ¬ify_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 : }
|