s3: net: implement json output for ads info
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Mon, 2 Jul 2018 14:21:59 +0000 (16:21 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 22 Sep 2018 04:05:06 +0000 (06:05 +0200)
Add the switch '--json' 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.

Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
Signed-off-by: Philipp Gesang <philipp.gesang@intra2net.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/utils/net.c
source3/utils/net.h
source3/utils/net_ads.c
source3/utils/wscript_build

index b3bd4b671181d6ca7384ed83203dd2681492d2e6..7f07644b6113b906b6a429c753858c728a1803ac 100644 (file)
@@ -973,6 +973,7 @@ static struct functable net_func[] = {
                /* Options for 'net ads join or leave' */
                {"no-dns-updates", 0, POPT_ARG_NONE, &c->opt_no_dns_updates},
                {"keep-account", 0, POPT_ARG_NONE, &c->opt_keep_account},
+               {"json", 0, POPT_ARG_NONE, &c->opt_json},
                POPT_COMMON_SAMBA
                { 0, 0, 0, 0}
        };
index 5e70fd3aafadfedb1cf1557434d49847d43cc0c7..0d01ad450102e9be0d8f3d95013f6ab8977b9605 100644 (file)
@@ -86,6 +86,7 @@ struct net_context {
        const char *opt_precheck;
        int opt_no_dns_updates;
        int opt_keep_account;
+       int opt_json;
 
        int opt_have_ip;
        struct sockaddr_storage opt_dest_ip;
index afe47dad83965d7848d36ab2950a9f0e3ce8d7cb..416a7b8d9273a5a13474ca1ee15b6796ef1da63a 100644 (file)
@@ -173,6 +173,123 @@ 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();
+       TALLOC_CTX *ctx = NULL;
+       char *json = NULL;
+
+       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 != 0) {
+               goto failure;
+       }
+
+       ret = json_add_string (&jsobj, "LDAP server name",
+                              ads->config.ldap_server_name);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_string (&jsobj, "Realm", ads->config.realm);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_int (&jsobj, "Server time offset",
+                           ads->auth.time_offset);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_int (&jsobj, "Last machine account password change",
+                           pass_time);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       if (json_is_invalid(&jsobj)) {
+               ret = -1;
+               goto failure;
+       }
+
+       ctx = talloc_new(NULL);
+       if (ctx == NULL) {
+               ret = -1;
+               d_fprintf(stderr, _("Out of memory\n"));
+
+               goto failure;
+       }
+
+       json = json_to_string(ctx, &jsobj);
+       if (json) {
+               d_printf("%s\n", json);
+       } else {
+               ret = -1;
+               d_fprintf(stderr, _("error encoding to JSON\n"));
+       }
+
+       TALLOC_FREE(ctx);
+failure:
+       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 +325,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);
index 6793c6d5c8a4e52f6cbefd4b14b7264b95898fe1..c6d1c29b3101cee94665848b3a554a1098d16a89 100644 (file)
@@ -263,6 +263,8 @@ bld.SAMBA3_BINARY('net',
                  printing_migrate
                  trusts_util
                  IDMAP_AUTORID_TDB
+                 jansson
+                 common_auth
                  ''')
 
 bld.SAMBA3_BINARY('mvxattr',