9d1478
From 6dcf7dcc04af4b77829f182a698beb59fc6f4341 Mon Sep 17 00:00:00 2001
9d1478
From: Rob Crittenden <rcritten@redhat.com>
9d1478
Date: Fri, 5 Apr 2019 11:17:22 -0400
9d1478
Subject: [PATCH] Add interactive prompt for the LDAP bind password to
9d1478
 ipa-getkeytab
9d1478
9d1478
This provides a mechanism to bind over LDAP without exposing
9d1478
the password on the command-line.
9d1478
9d1478
https://pagure.io/freeipa/issue/631
9d1478
9d1478
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
9d1478
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
9d1478
Reviewed-By: Robbie Harwood <rharwood@redhat.com>
9d1478
Reviewed-By: Christian Heimes <cheimes@redhat.com>
9d1478
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
9d1478
Reviewed-By: Simo Sorce <ssorce@redhat.com>
9d1478
---
9d1478
 client/ipa-getkeytab.c     | 53 ++++++++++++++++++++++++++++++--------
9d1478
 client/man/ipa-getkeytab.1 |  9 ++++---
9d1478
 2 files changed, 48 insertions(+), 14 deletions(-)
9d1478
9d1478
diff --git a/client/ipa-getkeytab.c b/client/ipa-getkeytab.c
9d1478
index 6713a0c5f6352dc63dc0ec24d4ccaec4c3ba31ae..8a5e98bed1947344247f9d6146e595d5f7f7a963 100644
9d1478
--- a/client/ipa-getkeytab.c
9d1478
+++ b/client/ipa-getkeytab.c
9d1478
@@ -626,7 +626,16 @@ done:
9d1478
     return ret;
9d1478
 }
9d1478
 
9d1478
-static char *ask_password(krb5_context krbctx)
9d1478
+/* Prompt for either a password.
9d1478
+ * This can be either asking for a new or existing password.
9d1478
+ *
9d1478
+ * To set a new password provide values for both prompt1 and prompt2 and
9d1478
+ * set match=true to enforce that the two entered passwords match.
9d1478
+ *
9d1478
+ * To prompt for an existing password provide prompt1 and set match=false.
9d1478
+ */
9d1478
+static char *ask_password(krb5_context krbctx, char *prompt1, char *prompt2,
9d1478
+                          bool match)
9d1478
 {
9d1478
     krb5_prompt ap_prompts[2];
9d1478
     krb5_data k5d_pw0;
9d1478
@@ -634,24 +643,27 @@ static char *ask_password(krb5_context krbctx)
9d1478
     char pw0[256];
9d1478
     char pw1[256];
9d1478
     char *password;
9d1478
+    int num_prompts = match ? 2:1;
9d1478
 
9d1478
     k5d_pw0.length = sizeof(pw0);
9d1478
     k5d_pw0.data = pw0;
9d1478
-    ap_prompts[0].prompt = _("New Principal Password");
9d1478
+    ap_prompts[0].prompt = prompt1;
9d1478
     ap_prompts[0].hidden = 1;
9d1478
     ap_prompts[0].reply = &k5d_pw0;
9d1478
 
9d1478
-    k5d_pw1.length = sizeof(pw1);
9d1478
-    k5d_pw1.data = pw1;
9d1478
-    ap_prompts[1].prompt = _("Verify Principal Password");
9d1478
-    ap_prompts[1].hidden = 1;
9d1478
-    ap_prompts[1].reply = &k5d_pw1;
9d1478
+    if (match) {
9d1478
+        k5d_pw1.length = sizeof(pw1);
9d1478
+        k5d_pw1.data = pw1;
9d1478
+        ap_prompts[1].prompt = prompt2;
9d1478
+        ap_prompts[1].hidden = 1;
9d1478
+        ap_prompts[1].reply = &k5d_pw1;
9d1478
+    }
9d1478
 
9d1478
     krb5_prompter_posix(krbctx, NULL,
9d1478
                 NULL, NULL,
9d1478
-                2, ap_prompts);
9d1478
+                num_prompts, ap_prompts);
9d1478
 
9d1478
-    if (strcmp(pw0, pw1)) {
9d1478
+    if (match && (strcmp(pw0, pw1))) {
9d1478
         fprintf(stderr, _("Passwords do not match!"));
9d1478
         return NULL;
9d1478
     }
9d1478
@@ -752,6 +764,7 @@ int main(int argc, const char *argv[])
9d1478
 	static const char *ca_cert_file = NULL;
9d1478
 	int quiet = 0;
9d1478
 	int askpass = 0;
9d1478
+	int askbindpw = 0;
9d1478
 	int permitted_enctypes = 0;
9d1478
 	int retrieve = 0;
9d1478
         struct poptOption options[] = {
9d1478
@@ -778,6 +791,8 @@ int main(int argc, const char *argv[])
9d1478
               _("LDAP DN"), _("DN to bind as if not using kerberos") },
9d1478
 	    { "bindpw", 'w', POPT_ARG_STRING, &bindpw, 0,
9d1478
               _("LDAP password"), _("password to use if not using kerberos") },
9d1478
+	    { NULL, 'W', POPT_ARG_NONE, &askbindpw, 0,
9d1478
+              _("Prompt for LDAP password"), NULL },
9d1478
 	    { "cacert", 0, POPT_ARG_STRING, &ca_cert_file, 0,
9d1478
               _("Path to the IPA CA certificate"), _("IPA CA certificate")},
9d1478
 	    { "ldapuri", 'H', POPT_ARG_STRING, &ldap_uri, 0,
9d1478
@@ -849,9 +864,24 @@ int main(int argc, const char *argv[])
9d1478
 		exit(2);
9d1478
 	}
9d1478
 
9d1478
+    if (askbindpw && bindpw != NULL) {
9d1478
+		fprintf(stderr, _("Bind password already provided (-w).\n"));
9d1478
+		if (!quiet) {
9d1478
+			poptPrintUsage(pc, stderr, 0);
9d1478
+		}
9d1478
+		exit(2);
9d1478
+    }
9d1478
+
9d1478
+    if (askbindpw) {
9d1478
+		bindpw = ask_password(krbctx, _("Enter LDAP password"), NULL, false);
9d1478
+		if (!bindpw) {
9d1478
+			exit(2);
9d1478
+		}
9d1478
+    }
9d1478
+
9d1478
 	if (NULL!=binddn && NULL==bindpw) {
9d1478
 		fprintf(stderr,
9d1478
-                        _("Bind password required when using a bind DN.\n"));
9d1478
+                        _("Bind password required when using a bind DN (-w or -W).\n"));
9d1478
 		if (!quiet)
9d1478
 			poptPrintUsage(pc, stderr, 0);
9d1478
 		exit(10);
9d1478
@@ -915,7 +945,8 @@ int main(int argc, const char *argv[])
9d1478
     }
9d1478
 
9d1478
         if (askpass) {
9d1478
-		password = ask_password(krbctx);
9d1478
+		password = ask_password(krbctx, _("New Principal Password"),
9d1478
+               	                _("Verify Principal Password"), true);
9d1478
 		if (!password) {
9d1478
 			exit(2);
9d1478
 		}
9d1478
diff --git a/client/man/ipa-getkeytab.1 b/client/man/ipa-getkeytab.1
9d1478
index 39ff0d5da85b5a641328a512feeb06bc9c1ab9d7..6e7fdf39ee4e28772365edafd4c7e86d0c37d343 100644
9d1478
--- a/client/man/ipa-getkeytab.1
9d1478
+++ b/client/man/ipa-getkeytab.1
9d1478
@@ -21,7 +21,7 @@
9d1478
 .SH "NAME"
9d1478
 ipa\-getkeytab \- Get a keytab for a Kerberos principal
9d1478
 .SH "SYNOPSIS"
9d1478
-ipa\-getkeytab \fB\-p\fR \fIprincipal\-name\fR \fB\-k\fR \fIkeytab\-file\fR [ \fB\-e\fR \fIencryption\-types\fR ] [ \fB\-s\fR \fIipaserver\fR ] [ \fB\-q\fR ] [ \fB\-D\fR|\fB\-\-binddn\fR \fIBINDDN\fR ] [ \fB\-w|\-\-bindpw\fR ] [ \fB\-P\fR|\fB\-\-password\fR \fIPASSWORD\fR ] [ \fB\-\-cacert \fICACERT\fR ] [ \fB\-H|\-\-ldapuri \fIURI\fR ] [ \fB\-Y|\-\-mech \fIGSSAPI|EXTERNAL\fR ] [ \fB\-r\fR ]
9d1478
+ipa\-getkeytab \fB\-p\fR \fIprincipal\-name\fR \fB\-k\fR \fIkeytab\-file\fR [ \fB\-e\fR \fIencryption\-types\fR ] [ \fB\-s\fR \fIipaserver\fR ] [ \fB\-q\fR ] [ \fB\-D\fR|\fB\-\-binddn\fR \fIBINDDN\fR ] [ \fB\-w|\-\-bindpw\fR ] [ \fB-W\fR ] [ \fB\-P\fR|\fB\-\-password\fR \fIPASSWORD\fR ] [ \fB\-\-cacert \fICACERT\fR ] [ \fB\-H|\-\-ldapuri \fIURI\fR ] [ \fB\-Y|\-\-mech \fIGSSAPI|EXTERNAL\fR ] [ \fB\-r\fR ]
9d1478
 
9d1478
 .SH "DESCRIPTION"
9d1478
 Retrieves a Kerberos \fIkeytab\fR.
9d1478
@@ -44,7 +44,7 @@ provided, so the principal name is just the service
9d1478
 name and hostname (ldap/foo.example.com from the
9d1478
 example above).
9d1478
 
9d1478
-ipa-getkeytab is used during IPA client enrollment to retrieve a host service principal and store it in /etc/krb5.keytab. It is possible to retrieve the keytab without Kerberos credentials if the host was pre\-created with a one\-time password. The keytab can be retrieved by binding as the host and authenticating with this one\-time password. The \fB\-D|\-\-binddn\fR and \fB\-w|\-\-bindpw\fR options are used for this authentication.
9d1478
+ipa-getkeytab is used during IPA client enrollment to retrieve a host service principal and store it in /etc/krb5.keytab. It is possible to retrieve the keytab without Kerberos credentials if the host was pre\-created with a one\-time password. The keytab can be retrieved by binding as the host and authenticating with this one\-time password. The \fB\-D|\-\-binddn\fR \fB\-w|\-\-bindpw\fR options are used for this authentication. \fB-W\fR can be used instead of \fB\-w|\-\-bindpw\fR to interactively prompt for the bind password.
9d1478
 
9d1478
 \fBWARNING:\fR retrieving the keytab resets the secret for the Kerberos principal.
9d1478
 This renders all other keytabs for that principal invalid.
9d1478
@@ -98,11 +98,14 @@ DES cbc mode with RSA\-MD4
9d1478
 Use this password for the key instead of one randomly generated.
9d1478
 .TP
9d1478
 \fB\-D, \-\-binddn\fR
9d1478
-The LDAP DN to bind as when retrieving a keytab without Kerberos credentials. Generally used with the \fB\-w\fR option.
9d1478
+The LDAP DN to bind as when retrieving a keytab without Kerberos credentials. Generally used with the \fB\-w\fR or \fB\-W\fR options.
9d1478
 .TP
9d1478
 \fB\-w, \-\-bindpw\fR
9d1478
 The LDAP password to use when not binding with Kerberos. \fB\-D\fR and \fB\-w\fR can not be used together with \fB\-Y\fR.
9d1478
 .TP
9d1478
+\fB\-W\fR
9d1478
+Interactive prompt for the bind password. \fB\-D\fR and \fB\-W\fR can not be used together with \fB\-Y\fR
9d1478
+.TP
9d1478
 \fB\-\-cacert\fR
9d1478
 The path to the IPA CA certificate used to validate LDAPS/STARTTLS connections.
9d1478
 Defaults to /etc/ipa/ca.crt
9d1478
-- 
9d1478
2.25.2
9d1478