Commit 635ec366d7f49f95c3c0ad2ce06a62fdc7c5d91a

Patrick Steinhardt 2019-04-16T10:51:43

examples: honor allowed credential types when prompting user Credential callback are being passed a bitset that indicates which credential types are allowed in the current context. In our examples code, we completely ignore that field and always return username/password credentials, which doesn't necessarily make sense e.g. when only SSH keys are allowed. Refactor the code and only return username/password credentials in the case where `USERPASS_PLAINTEXT` credentials are allowed. Otherwise, return a positive error code to indicate that no credentials could be acquired.

diff --git a/examples/common.c b/examples/common.c
index f1ee27e..ee47107 100644
--- a/examples/common.c
+++ b/examples/common.c
@@ -330,6 +330,19 @@ error:
 	return error;
 }
 
+static int ask(char **out, const char *prompt)
+{
+	printf("%s ", prompt);
+	fflush(stdout);
+
+	if (!readline(out)) {
+		fprintf(stderr, "Could not read response: %s", strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
 int cred_acquire_cb(git_cred **out,
 		const char *url,
 		const char *username_from_url,
@@ -337,31 +350,22 @@ int cred_acquire_cb(git_cred **out,
 		void *payload)
 {
 	char *username = NULL, *password = NULL;
-	int error;
+	int error = 1;
 
 	UNUSED(url);
 	UNUSED(username_from_url);
-	UNUSED(allowed_types);
 	UNUSED(payload);
 
-	printf("Username: ");
-	if (readline(&username) < 0) {
-		fprintf(stderr, "Unable to read username: %s", strerror(errno));
-		return -1;
-	}
+	if (allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) {
+		if ((error = ask(&username, "Username:")) < 0 ||
+		    (error = ask(&password, "Password:")) < 0)
+			goto out;
 
-	/* Yup. Right there on your terminal. Careful where you copy/paste output. */
-	printf("Password: ");
-	if (readline(&password) < 0) {
-		fprintf(stderr, "Unable to read password: %s", strerror(errno));
-		free(username);
-		return -1;
+		error = git_cred_userpass_plaintext_new(out, username, password);
 	}
 
-	error = git_cred_userpass_plaintext_new(out, username, password);
-
+out:
 	free(username);
 	free(password);
-
 	return error;
 }