[RFC PATCH v3 4/5] s3: net: implement json output for ads info

Philipp Gesang philipp.gesang at intra2net.com
Thu Jul 12 07:04:08 UTC 2018


Add the switch '-j' to 'net' to format the output as JSON.

The rationale is to supply the information in a machine-readable
fashion to complement the text version of the output which is
neither particularly well defined nor locale-safe.

The output differs from that of plain 'info' in that times are
not formatted as timestamps.

Currently affects only the 'net ads info' subcommand.

Signed-off-by: Philipp Gesang <philipp.gesang at intra2net.com>
---
 source3/utils/net.c         |   1 +
 source3/utils/net.h         |   1 +
 source3/utils/net_ads.c     | 114 ++++++++++++++++++++++++++++++++++++++++++++
 source3/utils/wscript_build |   2 +
 4 files changed, 118 insertions(+)

diff --git a/source3/utils/net.c b/source3/utils/net.c
index 44daa6088ca..57b853a684a 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -973,6 +973,7 @@ static struct functable net_func[] = {
 		{"precheck", 0, POPT_ARG_STRING, &c->opt_precheck},
 		/* Options for 'net ads join' */
 		{"no-dns-updates", 0, POPT_ARG_NONE, &c->opt_no_dns_updates},
+		{"json", 'j', POPT_ARG_NONE, &c->opt_json},
 		POPT_COMMON_SAMBA
 		{ 0, 0, 0, 0}
 	};
diff --git a/source3/utils/net.h b/source3/utils/net.h
index d6dfeb6208f..af748c0275f 100644
--- a/source3/utils/net.h
+++ b/source3/utils/net.h
@@ -85,6 +85,7 @@ struct net_context {
 	int opt_wipe;
 	const char *opt_precheck;
 	int opt_no_dns_updates;
+	int opt_json;
 
 	int opt_have_ip;
 	struct sockaddr_storage opt_dest_ip;
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index ffa67d8f525..c2350ca027f 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -173,6 +173,116 @@ static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
 }
 
 
+#ifdef HAVE_JANSSON
+#include <jansson.h>
+#include "audit_logging.h" /* various JSON helpers */
+#include "auth/common_auth.h"
+
+/*
+ * note: JSON output deliberately bypasses gettext so as to provide the same
+ * output irrespective of the locale.
+ */
+
+static int net_ads_info_json(ADS_STRUCT *ads)
+{
+	int ret = 0;
+	char addr[INET6_ADDRSTRLEN];
+	time_t pass_time;
+	struct json_object jsobj = json_new_object();
+
+	if (json_is_invalid(&jsobj)) {
+		d_fprintf(stderr, _("error setting up JSON value\n"));
+
+		goto failure;
+	}
+
+	pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
+
+	print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
+
+	ret = json_add_string (&jsobj, "LDAP server", addr);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_string (&jsobj, "LDAP server name", ads->config.ldap_server_name);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_string (&jsobj, "Realm", ads->config.realm);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_int (&jsobj, "Server time offset", ads->auth.time_offset);
+	if (ret) {
+		goto failure;
+	}
+
+	ret = json_add_int (&jsobj, "Last machine account password change", pass_time);
+	if (ret) {
+		goto failure;
+	}
+
+	if (json_is_invalid(&jsobj)) {
+		ret = -1;
+		goto failure;
+	}
+
+	if (jsobj.root == NULL) {
+		ret = -1;
+		goto failure;
+	}
+
+	json = json_dumps(jsobj.root, 0);
+	if (json) {
+		d_printf("%s\n", json);
+		free (json);
+	} else {
+		ret = -1;
+		d_fprintf(stderr, _("error encoding to JSON\n"));
+	}
+
+failure:
+	json_free(&jsobj);
+	ads_destroy(&ads);
+
+	return ret;
+}
+
+#else /* [HAVE_JANSSON] */
+
+static int net_ads_info_json(ADS_STRUCT *)
+{
+	d_fprintf(stderr, _("JSON support not available\n"));
+
+	return -1;
+}
+
+#endif /* [HAVE_JANSSON] */
+
+
 
 static int net_ads_info(struct net_context *c, int argc, const char **argv)
 {
@@ -208,6 +318,10 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
 		d_fprintf( stderr, _("Failed to get server's current time!\n"));
 	}
 
+	if (c->opt_json) {
+		return net_ads_info_json(ads);
+	}
+
 	pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
 
 	print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
diff --git a/source3/utils/wscript_build b/source3/utils/wscript_build
index 8b4d890d485..09b3306d0a4 100644
--- a/source3/utils/wscript_build
+++ b/source3/utils/wscript_build
@@ -248,6 +248,8 @@ bld.SAMBA3_BINARY('net',
                  printing_migrate
                  trusts_util
                  IDMAP_AUTORID_TDB
+                 jansson
+                 common_auth
                  ''')
 
 bld.SAMBA3_BINARY('mvxattr',
-- 
2.13.6




More information about the samba-technical mailing list