-/*
+/*
Unix SMB/CIFS implementation.
status reporting
Copyright (C) Andrew Tridgell 1994-1998
#include "serverid.h"
#include "status_profile.h"
#include "status.h"
+#include "status_json.h"
#include "smbd/notifyd/notifyd_db.h"
#include "cmdline_contexts.h"
#include "locking/leases_db.h"
#include "lib/util/string_wrappers.h"
+#include "lib/param/param.h"
+
+#ifdef HAVE_JANSSON
+#include <jansson.h>
+#include "audit_logging.h" /* various JSON helpers */
+#include "auth/common_auth.h"
+#endif /* HAVE_JANSSON */
#define SMB_MAXPIDS 2048
static uid_t Ucrit_uid = 0; /* added by OH */
static unsigned int Ucrit_checkUid(uid_t uid)
{
- if ( !Ucrit_IsActive )
+ if ( !Ucrit_IsActive )
return 1;
- if ( uid == Ucrit_uid )
+ if ( uid == Ucrit_uid )
return 1;
return 0;
{
int i;
- if ( !Ucrit_IsActive )
+ if ( !Ucrit_IsActive )
return 1;
for (i=0;i<Ucrit_MaxPid;i++) {
return True;
}
+static int print_share_mode_stdout(struct traverse_state *state,
+ const char *pid,
+ const char *user_name,
+ const char *denymode,
+ int access_mask,
+ const char *rw,
+ const char *oplock,
+ const char *servicepath,
+ const char *filename,
+ const char *timestr)
+{
+ if (state->first) {
+ d_printf("\nLocked files:\n");
+ d_printf("Pid User(ID) DenyMode Access R/W Oplock SharePath Name Time\n");
+ d_printf("--------------------------------------------------------------------------------------------------\n");
+
+ state->first = false;
+ }
+
+ d_printf("%-11s %-9s %-10s 0x%-8x %-10s %-14s %s %s %s",
+ pid, user_name, denymode, access_mask, rw, oplock,
+ servicepath, filename, timestr);
+ return 0;
+}
+
+static int prepare_share_mode(struct traverse_state *state)
+{
+ if (!state->json_output) {
+ /* only print header line if there are open files */
+ state->first = true;
+ } else {
+ add_section_to_json(state, "open_files");
+ }
+ return 0;
+}
+
+static uint32_t map_share_mode_to_deny_mode(
+ uint32_t share_access, uint32_t private_options)
+{
+ switch (share_access & ~FILE_SHARE_DELETE) {
+ case FILE_SHARE_NONE:
+ return DENY_ALL;
+ case FILE_SHARE_READ:
+ return DENY_WRITE;
+ case FILE_SHARE_WRITE:
+ return DENY_READ;
+ case FILE_SHARE_READ|FILE_SHARE_WRITE:
+ return DENY_NONE;
+ }
+ if (private_options & NTCREATEX_FLAG_DENY_DOS) {
+ return DENY_DOS;
+ } else if (private_options & NTCREATEX_FLAG_DENY_FCB) {
+ return DENY_FCB;
+ }
+
+ return (uint32_t)-1;
+}
+
static int print_share_mode(struct file_id fid,
const struct share_mode_data *d,
const struct share_mode_entry *e,
void *private_data)
{
- bool resolve_uids = *((bool *)private_data);
- static int count;
const char *denymode = NULL;
uint denymode_int;
const char *oplock = NULL;
const char *filename = NULL;
const char *timestr = NULL;
const char *user_str = NULL;
+ uint32_t lstate;
+ struct traverse_state *state = (struct traverse_state *)private_data;
TALLOC_CTX *tmp_ctx = talloc_stackframe();
if (tmp_ctx == NULL) {
return 0;
}
- if (count==0) {
- d_printf("Locked files:\n");
- d_printf("Pid User(ID) DenyMode Access R/W Oplock SharePath Name Time\n");
- d_printf("--------------------------------------------------------------------------------------------------\n");
- }
- count++;
-
if (do_checks && !serverid_exists(&e->pid)) {
/* the process for this entry does not exist any more */
TALLOC_FREE(tmp_ctx);
if (Ucrit_checkPid(e->pid)) {
struct server_id_buf tmp;
pid = server_id_str_buf(e->pid, &tmp);
- if (resolve_uids) {
+ if (state->resolve_uids) {
user_str = talloc_asprintf(tmp_ctx, "%s", uidtoname(e->uid));
} else {
user_str = talloc_asprintf(tmp_ctx, "%u", (unsigned int)e->uid);
oplock = "LEVEL_II";
} else if (e->op_type == LEASE_OPLOCK) {
NTSTATUS status;
- uint32_t lstate;
status = leases_db_get(
&e->client_guid,
}
timestr = time_to_asc((time_t)e->time.tv_sec);
- d_printf("%-11s %-9s %-10s 0x%-8x %-10s %-14s %s %s %s",
- pid, user_str, denymode, (unsigned int)e->access_mask,
- rw, oplock, d->servicepath, filename, timestr);
+
+ if (!state->json_output) {
+ print_share_mode_stdout(state,
+ pid,
+ user_str,
+ denymode,
+ (unsigned int)e->access_mask,
+ rw,
+ oplock,
+ d->servicepath,
+ filename,
+ timestr);
+ } else {
+ print_share_mode_json(state,
+ d,
+ e,
+ fid,
+ user_str,
+ oplock,
+ lstate,
+ filename);
+ }
}
TALLOC_FREE(tmp_ctx);
return 0;
}
+static void print_brl_stdout(struct traverse_state *state,
+ char *pid,
+ char *id,
+ const char *desc,
+ intmax_t start,
+ intmax_t size,
+ const char *sharepath,
+ char *fname)
+{
+ if (state->first) {
+ d_printf("Byte range locks:\n");
+ d_printf("Pid dev:inode R/W start size SharePath Name\n");
+ d_printf("--------------------------------------------------------------------------------\n");
+
+ state->first = false;
+ }
+ d_printf("%-10s %-15s %-4s %-9jd %-9jd %-24s %-24s\n",
+ pid, id, desc, start, size, sharepath, fname);
+}
+
+static int prepare_brl(struct traverse_state *state)
+{
+ if (!state->json_output) {
+ /* only print header line if there are locked files */
+ state->first = true;
+ } else {
+ add_section_to_json(state, "byte_range_locks");
+ }
+ return 0;
+}
+
static void print_brl(struct file_id id,
- struct server_id pid,
+ struct server_id pid,
enum brl_type lock_type,
enum brl_flavour lock_flav,
br_off start,
br_off size,
void *private_data)
{
- static int count;
unsigned int i;
static const struct {
enum brl_type lock_type;
struct share_mode_lock *share_mode;
struct server_id_buf tmp;
struct file_id_buf ftmp;
-
- if (count==0) {
- d_printf("Byte range locks:\n");
- d_printf("Pid dev:inode R/W start size SharePath Name\n");
- d_printf("--------------------------------------------------------------------------------\n");
- }
- count++;
+ struct traverse_state *state = (struct traverse_state *)private_data;
share_mode = fetch_share_mode_unlocked(NULL, id);
if (share_mode) {
fname = share_mode_filename(NULL, share_mode);
+ sharepath = share_mode_servicepath(share_mode);
} else {
fname = talloc_strdup(NULL, "");
if (fname == NULL) {
}
}
- d_printf("%-10s %-15s %-4s %-9jd %-9jd %-24s %-24s\n",
- server_id_str_buf(pid, &tmp),
- file_id_str_buf(id, &ftmp),
- desc,
- (intmax_t)start, (intmax_t)size,
- sharepath, fname);
+ if (!state->json_output) {
+ print_brl_stdout(state,
+ server_id_str_buf(pid, &tmp),
+ file_id_str_buf(id, &ftmp),
+ desc,
+ (intmax_t)start,
+ (intmax_t)size,
+ sharepath,
+ fname);
+ } else {
+ print_brl_json(state,
+ pid,
+ id,
+ desc,
+ lock_flav,
+ (intmax_t)start,
+ (intmax_t)size,
+ sharepath,
+ fname);
+
+ }
TALLOC_FREE(fname);
TALLOC_FREE(share_mode);
return unknown_dialect;
}
+static int traverse_connections_stdout(struct traverse_state *state,
+ const char *servicename,
+ char *server_id,
+ const char *machine,
+ const char *timestr,
+ const char *encryption_cipher,
+ enum crypto_degree encryption_degree,
+ const char *signing_cipher,
+ enum crypto_degree signing_degree)
+{
+ fstring encryption;
+ fstring signing;
+
+ if (encryption_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(encryption, "%s", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(encryption, "anonymous(%s)", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(encryption, "partial(%s)", encryption_cipher);
+ } else {
+ fstr_sprintf(encryption, "-");
+ }
+ if (signing_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(signing, "%s", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(signing, "anonymous(%s)", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(signing, "partial(%s)", signing_cipher);
+ } else {
+ fstr_sprintf(signing, "-");
+ }
+
+ d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
+ servicename, server_id, machine, timestr, encryption, signing);
+
+ return 0;
+}
+
+static int prepare_connections(struct traverse_state *state)
+{
+ if (!state->json_output) {
+ /* always print header line */
+ d_printf("\n%-12s %-7s %-13s %-32s %-12s %-12s\n", "Service", "pid", "Machine", "Connected at", "Encryption", "Signing");
+ d_printf("---------------------------------------------------------------------------------------------\n");
+ } else {
+ add_section_to_json(state, "tcons");
+ }
+ return 0;
+}
+
static int traverse_connections(const struct connections_data *crec,
void *private_data)
{
- TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
struct server_id_buf tmp;
char *timestr = NULL;
int result = 0;
const char *encryption = "-";
+ enum crypto_degree encryption_degree = CRYPTO_DEGREE_NONE;
const char *signing = "-";
+ enum crypto_degree signing_degree = CRYPTO_DEGREE_NONE;
+ struct traverse_state *state = (struct traverse_state *)private_data;
+
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ if (tmp_ctx == NULL) {
+ return -1;
+ }
- if (crec->cnum == TID_FIELD_INVALID)
+ if (crec->cnum == TID_FIELD_INVALID) {
+ TALLOC_FREE(tmp_ctx);
return 0;
+ }
if (do_checks &&
(!process_exists(crec->pid) || !Ucrit_checkUid(crec->uid))) {
+ TALLOC_FREE(tmp_ctx);
return 0;
}
- timestr = timestring(mem_ctx, crec->start);
+ timestr = timestring(tmp_ctx, nt_time_to_unix(crec->start));
if (timestr == NULL) {
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+ if (smbXsrv_is_encrypted(crec->encryption_flags) ||
+ smbXsrv_is_partially_encrypted(crec->encryption_flags))
+ {
switch (crec->cipher) {
case SMB_ENCRYPTION_GSSAPI:
encryption = "GSSAPI";
case SMB2_ENCRYPTION_AES128_GCM:
encryption = "AES-128-GCM";
break;
+ case SMB2_ENCRYPTION_AES256_CCM:
+ encryption = "AES-256-CCM";
+ break;
+ case SMB2_ENCRYPTION_AES256_GCM:
+ encryption = "AES-256-GCM";
+ break;
default:
encryption = "???";
- result = -1;
break;
}
+ if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_encrypted(crec->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (encryption_degree != CRYPTO_DEGREE_NONE &&
+ !crec->authenticated)
+ {
+ encryption_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
- if (smbXsrv_is_signed(crec->signing_flags)) {
+ if (smbXsrv_is_signed(crec->signing_flags) ||
+ smbXsrv_is_partially_signed(crec->signing_flags))
+ {
switch (crec->signing) {
case SMB2_SIGNING_MD5_SMB1:
signing = "HMAC-MD5";
break;
default:
signing = "???";
- result = -1;
break;
}
+ if (smbXsrv_is_signed(crec->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_signed(crec->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (signing_degree != CRYPTO_DEGREE_NONE &&
+ !crec->authenticated)
+ {
+ signing_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
- d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
- crec->servicename, server_id_str_buf(crec->pid, &tmp),
- crec->machine,
- timestr,
- encryption,
- signing);
+ if (!state->json_output) {
+ result = traverse_connections_stdout(state,
+ crec->servicename,
+ server_id_str_buf(crec->pid, &tmp),
+ crec->machine,
+ timestr,
+ encryption,
+ encryption_degree,
+ signing,
+ signing_degree);
+ } else {
+ result = traverse_connections_json(state,
+ crec,
+ encryption,
+ encryption_degree,
+ signing,
+ signing_degree);
+ }
TALLOC_FREE(timestr);
+ TALLOC_FREE(tmp_ctx);
return result;
}
+static int traverse_sessionid_stdout(struct traverse_state *state,
+ char *server_id,
+ char *uid_gid_str,
+ char *machine_hostname,
+ const char *dialect,
+ const char *encryption_cipher,
+ enum crypto_degree encryption_degree,
+ const char *signing_cipher,
+ enum crypto_degree signing_degree)
+{
+ fstring encryption;
+ fstring signing;
+
+ if (encryption_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(encryption, "%s", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(encryption, "anonymous(%s)", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(encryption, "partial(%s)", encryption_cipher);
+ } else {
+ fstr_sprintf(encryption, "-");
+ }
+ if (signing_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(signing, "%s", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(signing, "anonymous(%s)", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(signing, "partial(%s)", signing_cipher);
+ } else {
+ fstr_sprintf(signing, "-");
+ }
+
+ d_printf("%-7s %-25s %-41s %-17s %-20s %-21s\n",
+ server_id, uid_gid_str, machine_hostname, dialect, encryption,
+ signing);
+
+ return 0;
+}
+
+static int prepare_sessionid(struct traverse_state *state)
+{
+ if (!state->json_output) {
+ /* always print header line */
+ d_printf("\nSamba version %s\n",samba_version_string());
+ d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n", "PID", "Username", "Group", "Machine", "Protocol Version", "Encryption", "Signing");
+ d_printf("----------------------------------------------------------------------------------------------------------------------------------------\n");
+ } else {
+ add_section_to_json(state, "sessions");
+ }
+ return 0;
+
+}
+
static int traverse_sessionid(const char *key, struct sessionid *session,
void *private_data)
{
- TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
fstring uid_gid_str;
+ fstring uid_str;
+ fstring gid_str;
struct server_id_buf tmp;
char *machine_hostname = NULL;
int result = 0;
const char *encryption = "-";
+ enum crypto_degree encryption_degree = CRYPTO_DEGREE_NONE;
const char *signing = "-";
+ enum crypto_degree signing_degree = CRYPTO_DEGREE_NONE;
+ struct traverse_state *state = (struct traverse_state *)private_data;
+
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ if (tmp_ctx == NULL) {
+ return -1;
+ }
if (do_checks &&
(!process_exists(session->pid) ||
!Ucrit_checkUid(session->uid))) {
+ TALLOC_FREE(tmp_ctx);
return 0;
}
Ucrit_addPid(session->pid);
if (numeric_only) {
+ fstr_sprintf(gid_str, "%u", (unsigned int)session->gid);
+ fstr_sprintf(uid_str, "%u", (unsigned int)session->uid);
fstr_sprintf(uid_gid_str, "%-12u %-12u",
(unsigned int)session->uid,
(unsigned int)session->gid);
* The session is not fully authenticated yet.
*/
fstrcpy(uid_gid_str, "(auth in progress)");
+ fstrcpy(gid_str, "(auth in progress)");
+ fstrcpy(uid_str, "(auth in progress)");
} else {
/*
* In theory it should not happen that one of
if (session->uid != -1) {
uid_name = uidtoname(session->uid);
if (uid_name == NULL) {
+ TALLOC_FREE(tmp_ctx);
return -1;
}
}
if (session->gid != -1) {
gid_name = gidtoname(session->gid);
if (gid_name == NULL) {
+ TALLOC_FREE(tmp_ctx);
return -1;
}
}
+ fstr_sprintf(gid_str, "%s", gid_name);
+ fstr_sprintf(uid_str, "%s", uid_name);
fstr_sprintf(uid_gid_str, "%-12s %-12s",
uid_name, gid_name);
}
}
- machine_hostname = talloc_asprintf(mem_ctx, "%s (%s)",
+ machine_hostname = talloc_asprintf(tmp_ctx, "%s (%s)",
session->remote_machine,
session->hostname);
if (machine_hostname == NULL) {
+ TALLOC_FREE(tmp_ctx);
return -1;
}
- if (smbXsrv_is_encrypted(session->encryption_flags)) {
+ if (smbXsrv_is_encrypted(session->encryption_flags) ||
+ smbXsrv_is_partially_encrypted(session->encryption_flags)) {
switch (session->cipher) {
case SMB2_ENCRYPTION_AES128_CCM:
encryption = "AES-128-CCM";
result = -1;
break;
}
- } else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
- switch (session->cipher) {
- case SMB_ENCRYPTION_GSSAPI:
- encryption = "partial(GSSAPI)";
- break;
- case SMB2_ENCRYPTION_AES128_CCM:
- encryption = "partial(AES-128-CCM)";
- break;
- case SMB2_ENCRYPTION_AES128_GCM:
- encryption = "partial(AES-128-GCM)";
- break;
- case SMB2_ENCRYPTION_AES256_CCM:
- encryption = "partial(AES-256-CCM)";
- break;
- case SMB2_ENCRYPTION_AES256_GCM:
- encryption = "partial(AES-256-GCM)";
- break;
- default:
- encryption = "???";
- result = -1;
- break;
+ if (smbXsrv_is_encrypted(session->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (encryption_degree != CRYPTO_DEGREE_NONE &&
+ !session->authenticated)
+ {
+ encryption_degree = CRYPTO_DEGREE_ANONYMOUS;
}
}
- if (smbXsrv_is_signed(session->signing_flags)) {
+ if (smbXsrv_is_signed(session->signing_flags) ||
+ smbXsrv_is_partially_signed(session->signing_flags)) {
switch (session->signing) {
case SMB2_SIGNING_MD5_SMB1:
signing = "HMAC-MD5";
result = -1;
break;
}
- } else if (smbXsrv_is_partially_signed(session->signing_flags)) {
- switch (session->signing) {
- case SMB2_SIGNING_MD5_SMB1:
- signing = "partial(HMAC-MD5)";
- break;
- case SMB2_SIGNING_HMAC_SHA256:
- signing = "partial(HMAC-SHA256)";
- break;
- case SMB2_SIGNING_AES128_CMAC:
- signing = "partial(AES-128-CMAC)";
- break;
- case SMB2_SIGNING_AES128_GMAC:
- signing = "partial(AES-128-GMAC)";
- break;
- default:
- signing = "???";
- result = -1;
- break;
+ if (smbXsrv_is_signed(session->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_signed(session->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (signing_degree != CRYPTO_DEGREE_NONE &&
+ !session->authenticated)
+ {
+ signing_degree = CRYPTO_DEGREE_ANONYMOUS;
}
}
- d_printf("%-7s %-25s %-41s %-17s %-20s %-21s\n",
- server_id_str_buf(session->pid, &tmp),
- uid_gid_str,
- machine_hostname,
- session_dialect_str(session->connection_dialect),
- encryption,
- signing);
+ if (!state->json_output) {
+ traverse_sessionid_stdout(state,
+ server_id_str_buf(session->pid, &tmp),
+ uid_gid_str,
+ machine_hostname,
+ session_dialect_str(session->connection_dialect),
+ encryption,
+ encryption_degree,
+ signing,
+ signing_degree);
+ } else {
+ result = traverse_sessionid_json(state,
+ session,
+ uid_str,
+ gid_str,
+ encryption,
+ encryption_degree,
+ signing,
+ signing_degree,
+ session_dialect_str(session->connection_dialect));
+ }
TALLOC_FREE(machine_hostname);
+ TALLOC_FREE(tmp_ctx);
return result;
}
+static bool print_notify_rec_stdout(struct traverse_state *state,
+ const char *path,
+ char *server_id_str,
+ unsigned filter,
+ unsigned subdir_filter)
+{
+ d_printf("%s\\%s\\%x\\%x\n", path, server_id_str,
+ filter, subdir_filter);
+
+ return true;
+}
+
+static int prepare_notify(struct traverse_state *state)
+{
+ if (!state->json_output) {
+ /* don't print header line */
+ } else {
+ add_section_to_json(state, "notifies");
+ }
+ return 0;
+}
+
static bool print_notify_rec(const char *path, struct server_id server,
const struct notify_instance *instance,
void *private_data)
{
struct server_id_buf idbuf;
+ struct traverse_state *state = (struct traverse_state *)private_data;
+ bool result;
- d_printf("%s\\%s\\%x\\%x\n", path, server_id_str_buf(server, &idbuf),
- (unsigned)instance->filter,
- (unsigned)instance->subdir_filter);
+ if (!state->json_output) {
+ result = print_notify_rec_stdout(state,
+ path,
+ server_id_str_buf(server, &idbuf),
+ (unsigned)instance->filter,
+ (unsigned)instance->subdir_filter);
- return true;
+ } else {
+ result = print_notify_rec_json(state,
+ instance,
+ server,
+ path);
+ }
+
+ return result;
}
enum {
.val = 'n',
.descrip = "Numeric uid/gid"
},
+ {
+ .longName = "json",
+ .shortName = 'j',
+ .argInfo = POPT_ARG_NONE,
+ .arg = NULL,
+ .val = 'j',
+ .descrip = "JSON output"
+ },
{
.longName = "fast",
.shortName = 'f',
struct messaging_context *msg_ctx = NULL;
char *db_path;
bool ok;
+ struct loadparm_context *lp_ctx = NULL;
+ state.first = true;
+ state.json_output = false;
state.resolve_uids = false;
smb_init_locale();
TALLOC_FREE(frame);
exit(1);
}
- lp_set_cmdline("log level", "0");
+ lp_ctx = samba_cmdline_get_lp_ctx();
+ lpcfg_set_cmdline(lp_ctx, "log level", "0");
pc = samba_popt_get_context(getprogname(),
argc,
case 'n':
numeric_only = true;
break;
+ case 'j':
+ state.json_output = true;
+ break;
case 'f':
do_checks = false;
break;
sec_init();
+#ifdef HAVE_JANSSON
+ state.root_json = json_new_object();
+ if (!json_is_invalid(&state.root_json)) {
+ add_general_information_to_json(&state);
+ }
+#else /* HAVE_JANSSON */
+ if (state.json_output) {
+ fprintf(stderr, "JSON support not available, please install lib Jansson\n");
+ goto done;
+ }
+#endif /* HAVE_JANSSON */
+
if (getuid() != geteuid()) {
fprintf(stderr, "smbstatus should not be run setuid\n");
ret = 1;
if ( username )
Ucrit_addUid( nametouid(username) );
- if (verbose) {
+ if (verbose && !state.json_output) {
d_printf("using configfile = %s\n", get_dyn_CONFIGFILE());
}
switch (profile_only) {
case 'P':
/* Dump profile data */
- ok = status_profile_dump(verbose);
+ ok = status_profile_dump(verbose, &state);
ret = ok ? 0 : 1;
goto done;
case 'R':
/* Continuously display rate-converted data */
- ok = status_profile_rates(verbose);
- ret = ok ? 0 : 1;
+ if (!state.json_output) {
+ ok = status_profile_rates(verbose);
+ ret = ok ? 0 : 1;
+ } else {
+ fprintf(stderr, "Call rates not available in a json output.\n");
+ ret = 1;
+ }
goto done;
default:
break;
}
if ( show_processes ) {
- d_printf("\nSamba version %s\n",samba_version_string());
- d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n", "PID", "Username", "Group", "Machine", "Protocol Version", "Encryption", "Signing");
- d_printf("----------------------------------------------------------------------------------------------------------------------------------------\n");
-
- sessionid_traverse_read(traverse_sessionid, frame);
+ prepare_sessionid(&state);
+ sessionid_traverse_read(traverse_sessionid, &state);
if (processes_only) {
goto done;
if (brief) {
goto done;
}
+ prepare_connections(&state);
+ connections_forall_read(traverse_connections, &state);
- d_printf("\n%-12s %-7s %-13s %-32s %-12s %-12s\n", "Service", "pid", "Machine", "Connected at", "Encryption", "Signing");
- d_printf("---------------------------------------------------------------------------------------------\n");
-
- connections_forall_read(traverse_connections, frame);
-
- d_printf("\n");
+ if (!state.json_output) {
+ d_printf("\n");
+ }
if ( shares_only ) {
goto done;
fprintf(stderr, "This is normal if an SMB client has never "
"connected to your server.\n");
TALLOC_FREE(db_path);
- exit(0);
+ ret = 0;
+ goto done;
} else {
TALLOC_FREE(db);
TALLOC_FREE(db_path);
goto done;
}
- result = share_entry_forall(print_share_mode, &state.resolve_uids);
+ prepare_share_mode(&state);
+ result = share_entry_forall(print_share_mode, &state);
- if (result == 0) {
+ if (result == 0 && !state.json_output) {
fprintf(stderr, "No locked files\n");
- } else if (result < 0) {
+ } else if (result < 0 && !state.json_output) {
fprintf(stderr, "locked file list truncated\n");
}
- d_printf("\n");
+ if (!state.json_output) {
+ d_printf("\n");
+ }
if (show_brl) {
- brl_forall(print_brl, NULL);
+ prepare_brl(&state);
+ brl_forall(print_brl, &state);
}
locking_end();
}
if (show_notify) {
- notify_walk(msg_ctx, print_notify_rec, NULL);
+ prepare_notify(&state);
+ notify_walk(msg_ctx, print_notify_rec, &state);
}
done:
cmdline_messaging_context_free();
poptFreeContext(pc);
+#ifdef HAVE_JANSSON
+ if (state.json_output) {
+ d_printf("%s\n", json_to_string(frame, &state.root_json));
+ }
+ json_free(&state.root_json);
+#endif /* HAVE_JANSSON */
TALLOC_FREE(frame);
return ret;
}