c31b6fe
From 0a169bd9b2687293f74bb57694eb82f9769610c9 Mon Sep 17 00:00:00 2001
c31b6fe
From: Sumit Bose <sbose@redhat.com>
c31b6fe
Date: Wed, 27 Nov 2019 12:34:45 +0100
c31b6fe
Subject: [PATCH 2/6] tools: add show-computer command
c31b6fe
c31b6fe
The show-computer command prints the LDAP attributes of the related
c31b6fe
computer object from AD.
c31b6fe
c31b6fe
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1737342
c31b6fe
---
c31b6fe
 doc/adcli.xml      | 28 ++++++++++++++
c31b6fe
 library/adenroll.c | 78 +++++++++++++++++++++++++++++---------
c31b6fe
 library/adenroll.h |  5 +++
c31b6fe
 tools/computer.c   | 93 ++++++++++++++++++++++++++++++++++++++++++++++
c31b6fe
 tools/tools.c      |  1 +
c31b6fe
 tools/tools.h      |  4 ++
c31b6fe
 6 files changed, 191 insertions(+), 18 deletions(-)
c31b6fe
c31b6fe
diff --git a/doc/adcli.xml b/doc/adcli.xml
c31b6fe
index 9faf96a..1f93186 100644
c31b6fe
--- a/doc/adcli.xml
c31b6fe
+++ b/doc/adcli.xml
c31b6fe
@@ -93,6 +93,11 @@
c31b6fe
 		<arg choice="opt">--domain=domain.example.com</arg>
c31b6fe
 		<arg choice="plain">computer</arg>
c31b6fe
 	</cmdsynopsis>
c31b6fe
+	<cmdsynopsis>
c31b6fe
+		<command>adcli show-computer</command>
c31b6fe
+		<arg choice="opt">--domain=domain.example.com</arg>
c31b6fe
+		<arg choice="plain">computer</arg>
c31b6fe
+	</cmdsynopsis>
c31b6fe
 </refsynopsisdiv>
c31b6fe
 
c31b6fe
 <refsect1 id='general_overview'>
c31b6fe
@@ -811,6 +816,29 @@ Password for Administrator:
c31b6fe
 
c31b6fe
 </refsect1>
c31b6fe
 
c31b6fe
+<refsect1 id='show_computer_account'>
c31b6fe
+	<title>Show Computer Account Attributes</title>
c31b6fe
+
c31b6fe
+	<para><command>adcli show-computer</command> show the computer account
c31b6fe
+	attributes stored in AD. The account must already exist.</para>
c31b6fe
+
c31b6fe
+<programlisting>
c31b6fe
+$ adcli show-computer --domain=domain.example.com host2
c31b6fe
+Password for Administrator:
c31b6fe
+</programlisting>
c31b6fe
+
c31b6fe
+	<para>If the computer name contains a dot, then it is
c31b6fe
+	treated as fully qualified host name, otherwise it is treated
c31b6fe
+	as short computer name.</para>
c31b6fe
+
c31b6fe
+	<para>If no computer name is specified, then the host name of the
c31b6fe
+	computer adcli is running on is used, as returned by
c31b6fe
+	<literal>gethostname()</literal>.</para>
c31b6fe
+
c31b6fe
+	<para>The various global options can be used.</para>
c31b6fe
+
c31b6fe
+</refsect1>
c31b6fe
+
c31b6fe
 <refsect1 id='bugs'>
c31b6fe
 	<title>Bugs</title>
c31b6fe
 	<para>
c31b6fe
diff --git a/library/adenroll.c b/library/adenroll.c
c31b6fe
index 524663a..8d2adeb 100644
c31b6fe
--- a/library/adenroll.c
c31b6fe
+++ b/library/adenroll.c
c31b6fe
@@ -71,6 +71,21 @@ static krb5_enctype v51_earlier_enctypes[] = {
c31b6fe
 	0
c31b6fe
 };
c31b6fe
 
c31b6fe
+static char *default_ad_ldap_attrs[] =  {
c31b6fe
+	"sAMAccountName",
c31b6fe
+	"userPrincipalName",
c31b6fe
+	"msDS-KeyVersionNumber",
c31b6fe
+	"msDS-supportedEncryptionTypes",
c31b6fe
+	"dNSHostName",
c31b6fe
+	"servicePrincipalName",
c31b6fe
+	"operatingSystem",
c31b6fe
+	"operatingSystemVersion",
c31b6fe
+	"operatingSystemServicePack",
c31b6fe
+	"pwdLastSet",
c31b6fe
+	"userAccountControl",
c31b6fe
+	NULL,
c31b6fe
+};
c31b6fe
+
c31b6fe
 /* Some constants for the userAccountControl AD LDAP attribute, see e.g.
c31b6fe
  * https://support.microsoft.com/en-us/help/305144/how-to-use-the-useraccountcontrol-flags-to-manipulate-user-account-pro
c31b6fe
  * for details. */
c31b6fe
@@ -1213,19 +1228,6 @@ retrieve_computer_account (adcli_enroll *enroll)
c31b6fe
 	char *end;
c31b6fe
 	int ret;
c31b6fe
 
c31b6fe
-	char *attrs[] =  {
c31b6fe
-		"msDS-KeyVersionNumber",
c31b6fe
-		"msDS-supportedEncryptionTypes",
c31b6fe
-		"dNSHostName",
c31b6fe
-		"servicePrincipalName",
c31b6fe
-		"operatingSystem",
c31b6fe
-		"operatingSystemVersion",
c31b6fe
-		"operatingSystemServicePack",
c31b6fe
-		"pwdLastSet",
c31b6fe
-		"userAccountControl",
c31b6fe
-		NULL,
c31b6fe
-	};
c31b6fe
-
c31b6fe
 	assert (enroll->computer_dn != NULL);
c31b6fe
 	assert (enroll->computer_attributes == NULL);
c31b6fe
 
c31b6fe
@@ -1233,7 +1235,8 @@ retrieve_computer_account (adcli_enroll *enroll)
c31b6fe
 	assert (ldap != NULL);
c31b6fe
 
c31b6fe
 	ret = ldap_search_ext_s (ldap, enroll->computer_dn, LDAP_SCOPE_BASE,
c31b6fe
-	                         "(objectClass=*)", attrs, 0, NULL, NULL, NULL, -1,
c31b6fe
+	                         "(objectClass=*)", default_ad_ldap_attrs,
c31b6fe
+	                         0, NULL, NULL, NULL, -1,
c31b6fe
 	                         &enroll->computer_attributes);
c31b6fe
 
c31b6fe
 	if (ret != LDAP_SUCCESS) {
c31b6fe
@@ -2179,12 +2182,11 @@ adcli_enroll_load (adcli_enroll *enroll)
c31b6fe
 }
c31b6fe
 
c31b6fe
 adcli_result
c31b6fe
-adcli_enroll_update (adcli_enroll *enroll,
c31b6fe
-		     adcli_enroll_flags flags)
c31b6fe
+adcli_enroll_read_computer_account (adcli_enroll *enroll,
c31b6fe
+		                    adcli_enroll_flags flags)
c31b6fe
 {
c31b6fe
 	adcli_result res = ADCLI_SUCCESS;
c31b6fe
 	LDAP *ldap;
c31b6fe
-	char *value;
c31b6fe
 
c31b6fe
 	return_unexpected_if_fail (enroll != NULL);
c31b6fe
 
c31b6fe
@@ -2214,7 +2216,18 @@ adcli_enroll_update (adcli_enroll *enroll,
c31b6fe
 	}
c31b6fe
 
c31b6fe
 	/* Get information about the computer account */
c31b6fe
-	res = retrieve_computer_account (enroll);
c31b6fe
+	return retrieve_computer_account (enroll);
c31b6fe
+}
c31b6fe
+
c31b6fe
+adcli_result
c31b6fe
+adcli_enroll_update (adcli_enroll *enroll,
c31b6fe
+		     adcli_enroll_flags flags)
c31b6fe
+{
c31b6fe
+	adcli_result res = ADCLI_SUCCESS;
c31b6fe
+	LDAP *ldap;
c31b6fe
+	char *value;
c31b6fe
+
c31b6fe
+	res = adcli_enroll_read_computer_account (enroll, flags);
c31b6fe
 	if (res != ADCLI_SUCCESS)
c31b6fe
 		return res;
c31b6fe
 
c31b6fe
@@ -2242,6 +2255,35 @@ adcli_enroll_update (adcli_enroll *enroll,
c31b6fe
 	return enroll_join_or_update_tasks (enroll, flags);
c31b6fe
 }
c31b6fe
 
c31b6fe
+adcli_result
c31b6fe
+adcli_enroll_show_computer_attribute (adcli_enroll *enroll)
c31b6fe
+{
c31b6fe
+	LDAP *ldap;
c31b6fe
+	size_t c;
c31b6fe
+	char **vals;
c31b6fe
+	size_t v;
c31b6fe
+
c31b6fe
+	ldap = adcli_conn_get_ldap_connection (enroll->conn);
c31b6fe
+	assert (ldap != NULL);
c31b6fe
+
c31b6fe
+	for (c = 0; default_ad_ldap_attrs[c] != NULL; c++) {
c31b6fe
+		vals = _adcli_ldap_parse_values (ldap,
c31b6fe
+		                                 enroll->computer_attributes,
c31b6fe
+		                                 default_ad_ldap_attrs[c]);
c31b6fe
+		printf ("%s:\n", default_ad_ldap_attrs[c]);
c31b6fe
+		if (vals == NULL) {
c31b6fe
+			printf (" - not set -\n");
c31b6fe
+		} else {
c31b6fe
+			for (v = 0; vals[v] != NULL; v++) {
c31b6fe
+				printf (" %s\n", vals[v]);
c31b6fe
+			}
c31b6fe
+		}
c31b6fe
+		_adcli_strv_free (vals);
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	return ADCLI_SUCCESS;
c31b6fe
+}
c31b6fe
+
c31b6fe
 adcli_result
c31b6fe
 adcli_enroll_delete (adcli_enroll *enroll,
c31b6fe
                      adcli_enroll_flags delete_flags)
c31b6fe
diff --git a/library/adenroll.h b/library/adenroll.h
c31b6fe
index 1d5d00d..11eb517 100644
c31b6fe
--- a/library/adenroll.h
c31b6fe
+++ b/library/adenroll.h
c31b6fe
@@ -46,6 +46,11 @@ adcli_result       adcli_enroll_join                    (adcli_enroll *enroll,
c31b6fe
 adcli_result       adcli_enroll_update                  (adcli_enroll *enroll,
c31b6fe
 		                                         adcli_enroll_flags flags);
c31b6fe
 
c31b6fe
+adcli_result       adcli_enroll_read_computer_account   (adcli_enroll *enroll,
c31b6fe
+                                                         adcli_enroll_flags flags);
c31b6fe
+
c31b6fe
+adcli_result       adcli_enroll_show_computer_attribute (adcli_enroll *enroll);
c31b6fe
+
c31b6fe
 adcli_result       adcli_enroll_delete                  (adcli_enroll *enroll,
c31b6fe
                                                          adcli_enroll_flags delete_flags);
c31b6fe
 
c31b6fe
diff --git a/tools/computer.c b/tools/computer.c
c31b6fe
index ac8a203..c8b96a4 100644
c31b6fe
--- a/tools/computer.c
c31b6fe
+++ b/tools/computer.c
c31b6fe
@@ -964,3 +964,96 @@ adcli_tool_computer_delete (adcli_conn *conn,
c31b6fe
 	adcli_enroll_unref (enroll);
c31b6fe
 	return 0;
c31b6fe
 }
c31b6fe
+
c31b6fe
+int
c31b6fe
+adcli_tool_computer_show (adcli_conn *conn,
c31b6fe
+                          int argc,
c31b6fe
+                          char *argv[])
c31b6fe
+{
c31b6fe
+	adcli_enroll *enroll;
c31b6fe
+	adcli_result res;
c31b6fe
+	int opt;
c31b6fe
+
c31b6fe
+	struct option options[] = {
c31b6fe
+		{ "domain", required_argument, NULL, opt_domain },
c31b6fe
+		{ "domain-realm", required_argument, NULL, opt_domain_realm },
c31b6fe
+		{ "domain-controller", required_argument, NULL, opt_domain_controller },
c31b6fe
+		{ "login-user", required_argument, NULL, opt_login_user },
c31b6fe
+		{ "login-ccache", optional_argument, NULL, opt_login_ccache },
c31b6fe
+		{ "login-type", required_argument, NULL, opt_login_type },
c31b6fe
+		{ "no-password", no_argument, 0, opt_no_password },
c31b6fe
+		{ "stdin-password", no_argument, 0, opt_stdin_password },
c31b6fe
+		{ "prompt-password", no_argument, 0, opt_prompt_password },
c31b6fe
+		{ "verbose", no_argument, NULL, opt_verbose },
c31b6fe
+		{ "help", no_argument, NULL, 'h' },
c31b6fe
+		{ 0 },
c31b6fe
+	};
c31b6fe
+
c31b6fe
+	static adcli_tool_desc usages[] = {
c31b6fe
+		{ 0, "usage: adcli show-computer --domain=xxxx host1.example.com" },
c31b6fe
+		{ 0 },
c31b6fe
+	};
c31b6fe
+
c31b6fe
+	enroll = adcli_enroll_new (conn);
c31b6fe
+	if (enroll == NULL) {
c31b6fe
+		warnx ("unexpected memory problems");
c31b6fe
+		return -1;
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	while ((opt = adcli_tool_getopt (argc, argv, options)) != -1) {
c31b6fe
+		switch (opt) {
c31b6fe
+		case 'h':
c31b6fe
+		case '?':
c31b6fe
+		case ':':
c31b6fe
+			adcli_tool_usage (options, usages);
c31b6fe
+			adcli_tool_usage (options, common_usages);
c31b6fe
+			adcli_enroll_unref (enroll);
c31b6fe
+			return opt == 'h' ? 0 : 2;
c31b6fe
+		default:
c31b6fe
+			res = parse_option ((Option)opt, optarg, conn, enroll);
c31b6fe
+			if (res != ADCLI_SUCCESS) {
c31b6fe
+				adcli_enroll_unref (enroll);
c31b6fe
+				return res;
c31b6fe
+			}
c31b6fe
+			break;
c31b6fe
+		}
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	argc -= optind;
c31b6fe
+	argv += optind;
c31b6fe
+
c31b6fe
+	res = adcli_conn_connect (conn);
c31b6fe
+	if (res != ADCLI_SUCCESS) {
c31b6fe
+		warnx ("couldn't connect to %s domain: %s",
c31b6fe
+		       adcli_conn_get_domain_name (conn),
c31b6fe
+		       adcli_get_last_error ());
c31b6fe
+		adcli_enroll_unref (enroll);
c31b6fe
+		return -res;
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	if (argc == 1) {
c31b6fe
+		parse_fqdn_or_name (enroll, argv[0]);
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	res = adcli_enroll_read_computer_account (enroll, 0);
c31b6fe
+	if (res != ADCLI_SUCCESS) {
c31b6fe
+		warnx ("couldn't read data for %s: %s",
c31b6fe
+		       adcli_enroll_get_host_fqdn (enroll) != NULL
c31b6fe
+		           ? adcli_enroll_get_host_fqdn (enroll)
c31b6fe
+		           : adcli_enroll_get_computer_name (enroll),
c31b6fe
+		       adcli_get_last_error ());
c31b6fe
+		adcli_enroll_unref (enroll);
c31b6fe
+		return -res;
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	res = adcli_enroll_show_computer_attribute (enroll);
c31b6fe
+	if (res != ADCLI_SUCCESS) {
c31b6fe
+		warnx ("couldn't print data for %s: %s",
c31b6fe
+		       argv[0], adcli_get_last_error ());
c31b6fe
+		adcli_enroll_unref (enroll);
c31b6fe
+		return -res;
c31b6fe
+	}
c31b6fe
+
c31b6fe
+	adcli_enroll_unref (enroll);
c31b6fe
+	return 0;
c31b6fe
+}
c31b6fe
diff --git a/tools/tools.c b/tools/tools.c
c31b6fe
index fc9fa9a..9d422f2 100644
c31b6fe
--- a/tools/tools.c
c31b6fe
+++ b/tools/tools.c
c31b6fe
@@ -59,6 +59,7 @@ struct {
c31b6fe
 	{ "preset-computer", adcli_tool_computer_preset, "Pre setup computers accounts", },
c31b6fe
 	{ "reset-computer", adcli_tool_computer_reset, "Reset a computer account", },
c31b6fe
 	{ "delete-computer", adcli_tool_computer_delete, "Delete a computer account", },
c31b6fe
+	{ "show-computer", adcli_tool_computer_show, "Show computer account attributes stored in AD", },
c31b6fe
 	{ "create-user", adcli_tool_user_create, "Create a user account", },
c31b6fe
 	{ "delete-user", adcli_tool_user_delete, "Delete a user account", },
c31b6fe
 	{ "create-group", adcli_tool_group_create, "Create a group", },
c31b6fe
diff --git a/tools/tools.h b/tools/tools.h
c31b6fe
index 8cebbf9..3702875 100644
c31b6fe
--- a/tools/tools.h
c31b6fe
+++ b/tools/tools.h
c31b6fe
@@ -78,6 +78,10 @@ int       adcli_tool_computer_delete   (adcli_conn *conn,
c31b6fe
                                         int argc,
c31b6fe
                                         char *argv[]);
c31b6fe
 
c31b6fe
+int       adcli_tool_computer_show     (adcli_conn *conn,
c31b6fe
+                                        int argc,
c31b6fe
+                                        char *argv[]);
c31b6fe
+
c31b6fe
 int       adcli_tool_user_create       (adcli_conn *conn,
c31b6fe
                                         int argc,
c31b6fe
                                         char *argv[]);
c31b6fe
-- 
c31b6fe
2.25.1
c31b6fe