[RFC PATCH v2 3/3] s3: net: implement json output for ads lookup
Philipp Gesang
philipp.gesang at intra2net.com
Mon Jul 9 09:08:23 UTC 2018
Add JSON printer (option '-j') for the 'net ads lookup' command.
This outputs the same information as the plain version, with
integral ({LMNT,LM20} Token, NT Version) and boolean values
(Flags) not stringified.
Signed-off-by: Philipp Gesang <philipp.gesang at intra2net.com>
---
source3/utils/net_ads.c | 270 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 244 insertions(+), 26 deletions(-)
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 16332e6d3e4..dbfa266673d 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -41,6 +41,12 @@
#include "lib/param/loadparm.h"
#include "utils/net_dns.h"
+#ifdef HAVE_JANSSON
+#include <jansson.h>
+#include "audit_logging.h" /* various JSON helpers */
+#include "auth/common_auth.h"
+#endif /* [HAVE_JANSSON] */
+
#ifdef HAVE_ADS
/* when we do not have sufficient input parameters to contact a remote domain
@@ -55,6 +61,239 @@ static const char *assume_own_realm(struct net_context *c)
return NULL;
}
+#ifdef HAVE_JANSSON
+
+/*
+ * note: JSON output deliberately bypasses gettext so as to provide the same
+ * output irrespective of the locale.
+ */
+
+static int output_json(const struct json_object *jsobj)
+{
+ char *json = NULL;
+
+ if (json_is_invalid(jsobj)) {
+ return -1;
+ }
+
+ if (jsobj->root == NULL) {
+ return -1;
+ }
+
+ json = json_dumps(jsobj->root, 0);
+ if (!json) {
+ d_fprintf(stderr, _("error encoding to JSON\n"));
+ return -1;
+ }
+
+ d_printf("%s\n", json);
+ free (json);
+
+ return 0;
+}
+
+static int net_ads_cldap_netlogon_json(ADS_STRUCT *ads,
+ const char *addr,
+ const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
+{
+ struct json_object jsobj = json_empty_object;
+ struct json_object flagsobj = json_empty_object;
+ char response_type [32] = { '\0' };
+ int ret = 0;
+
+ if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
+ d_fprintf(stderr, _("error setting up JSON value\n"));
+
+ goto failure;
+ }
+
+ switch (reply->command) {
+ case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
+ strncpy(response_type, "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
+ sizeof(response_type));
+ break;
+ case LOGON_SAM_LOGON_RESPONSE_EX:
+ strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
+ sizeof(response_type));
+ break;
+ default:
+ snprintf(response_type, sizeof(response_type), "0x%x",
+ reply->command);
+ break;
+ }
+
+ ret = json_add_string(&jsobj, "Information for Domain Controller", addr);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Response Type", response_type);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is a PDC", reply->server_type & NBT_SERVER_PDC);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is a GC of the forest", reply->server_type & NBT_SERVER_GC);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is an LDAP server", reply->server_type & NBT_SERVER_LDAP);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Supports DS", reply->server_type & NBT_SERVER_DS);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is running a KDC", reply->server_type & NBT_SERVER_KDC);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is running time services", reply->server_type & NBT_SERVER_TIMESERV);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is the closest DC", reply->server_type & NBT_SERVER_CLOSEST);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is writable", reply->server_type & NBT_SERVER_WRITABLE);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Has a hardware clock", reply->server_type & NBT_SERVER_GOOD_TIMESERV);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is a non-domain NC serviced by LDAP server", reply->server_type & NBT_SERVER_NDNC);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is NT6 DC that has some secrets", reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Is NT6 DC that has all secrets", reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services", reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later", reply->server_type & NBT_SERVER_DS_8);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Forest", reply->forest);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
+ if (ret) {
+ goto failure;
+ }
+
+
+ ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
+ if (ret) {
+ goto failure;
+ }
+
+ if (*reply->user_name) {
+ ret = json_add_string(&jsobj, "User name", reply->user_name);
+ if (ret) {
+ goto failure;
+ }
+ }
+
+ ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = json_add_object(&jsobj, "Flags", &flagsobj);
+ if (ret) {
+ goto failure;
+ }
+
+ ret = output_json(&jsobj);
+ json_free(&jsobj); /* frees flagsobj recursively */
+
+ return ret;
+
+failure:
+ json_free(&flagsobj);
+ json_free(&jsobj);
+
+ return ret;
+}
+
+#else /* [HAVE_JANSSON] */
+
+static int net_ads_cldap_netlogon_json(ADS_STRUCT *, const char *,
+ const struct NETLOGON_SAM_LOGON_RESPONSE_EX *)
+{
+ d_fprintf(stderr, _("JSON support not available\n"));
+
+ return -1;
+}
+
+#endif /* [HAVE_JANSSON] */
+
/*
do a cldap netlogon query
*/
@@ -70,6 +309,10 @@ static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
return -1;
}
+ if (c->opt_json) {
+ return net_ads_cldap_netlogon_json(ads, addr, &reply);
+ }
+
d_printf(_("Information for Domain Controller: %s\n\n"),
addr);
@@ -174,14 +417,6 @@ 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)
{
@@ -246,24 +481,7 @@ static int net_ads_info_json(ADS_STRUCT *ads)
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"));
- }
+ ret = output_json(&jsobj);
failure:
json_free(&jsobj);
--
2.13.6
More information about the samba-technical
mailing list