You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
6.6 KiB
195 lines
6.6 KiB
From 2f3cd781879e7063fcd996389071458587623e1c Mon Sep 17 00:00:00 2001
|
|
From: Sumit Bose <sbose@redhat.com>
|
|
Date: Mon, 22 Aug 2022 11:37:07 +0200
|
|
Subject: [PATCH 24/24] oidc_child: add --client-secret-stdin option
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Since there is the use-case of confidential client which requires that
|
|
the client secret must be sent to the IdP we should handle it
|
|
confidentially by not putting it on the command line but sending it via
|
|
stdin.
|
|
|
|
Resolves: https://github.com/SSSD/sssd/issues/6146
|
|
|
|
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
|
|
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
(cherry picked from commit 1a475e0c537c905c80406ceb88c7b34e6400bc40)
|
|
|
|
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
|
---
|
|
src/oidc_child/oidc_child.c | 89 ++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 82 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/src/oidc_child/oidc_child.c b/src/oidc_child/oidc_child.c
|
|
index c8d35d5d8..7758cdc25 100644
|
|
--- a/src/oidc_child/oidc_child.c
|
|
+++ b/src/oidc_child/oidc_child.c
|
|
@@ -34,7 +34,7 @@
|
|
#include "util/atomic_io.h"
|
|
|
|
#define IN_BUF_SIZE 4096
|
|
-static errno_t read_device_code_from_stdin(struct devicecode_ctx *dc_ctx)
|
|
+static errno_t read_from_stdin(TALLOC_CTX *mem_ctx, char **out)
|
|
{
|
|
uint8_t buf[IN_BUF_SIZE];
|
|
ssize_t len;
|
|
@@ -56,7 +56,7 @@ static errno_t read_device_code_from_stdin(struct devicecode_ctx *dc_ctx)
|
|
return EINVAL;
|
|
}
|
|
|
|
- str = talloc_strndup(dc_ctx, (char *) buf, len);
|
|
+ str = talloc_strndup(mem_ctx, (char *) buf, len);
|
|
sss_erase_mem_securely(buf, IN_BUF_SIZE);
|
|
if (str == NULL) {
|
|
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strndup failed.\n");
|
|
@@ -65,21 +65,72 @@ static errno_t read_device_code_from_stdin(struct devicecode_ctx *dc_ctx)
|
|
talloc_set_destructor((void *) str, sss_erase_talloc_mem_securely);
|
|
|
|
if (strlen(str) != len) {
|
|
- DEBUG(SSSDBG_CRIT_FAILURE,
|
|
- "Input contains additional data, "
|
|
- "only JSON encoded device code expected.\n");
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Input contains additional data.\n");
|
|
talloc_free(str);
|
|
return EINVAL;
|
|
}
|
|
|
|
+ *out = str;
|
|
+
|
|
+ return EOK;
|
|
+}
|
|
+
|
|
+static errno_t read_device_code_from_stdin(struct devicecode_ctx *dc_ctx,
|
|
+ const char **out)
|
|
+{
|
|
+ char *str;
|
|
+ errno_t ret;
|
|
+ char *sep;
|
|
+
|
|
+ ret = read_from_stdin(dc_ctx, &str);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "read_from_stdin failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (out != NULL) {
|
|
+ /* expect the client secret in the first line */
|
|
+ sep = strchr(str, '\n');
|
|
+ if (sep == NULL) {
|
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
+ "Format error, expecting client secret and JSON data.\n");
|
|
+ talloc_free(str);
|
|
+ return EINVAL;
|
|
+ }
|
|
+ *sep = '\0';
|
|
+ *out = str;
|
|
+ sep++;
|
|
+ } else {
|
|
+ sep = str;
|
|
+ }
|
|
+
|
|
clean_http_data(dc_ctx);
|
|
- dc_ctx->http_data = str;
|
|
+ dc_ctx->http_data = talloc_strdup(dc_ctx, sep);
|
|
|
|
DEBUG(SSSDBG_TRACE_ALL, "JSON device code: [%s].\n", dc_ctx->http_data);
|
|
|
|
return EOK;
|
|
}
|
|
|
|
+static errno_t read_client_secret_from_stdin(struct devicecode_ctx *dc_ctx,
|
|
+ const char **out)
|
|
+{
|
|
+ char *str;
|
|
+ errno_t ret;
|
|
+
|
|
+ ret = read_from_stdin(dc_ctx, &str);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE, "read_from_stdin failed.\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ *out = str;
|
|
+
|
|
+ DEBUG(SSSDBG_TRACE_ALL, "Client secret: [%s].\n", *out);
|
|
+
|
|
+ return EOK;
|
|
+}
|
|
+
|
|
static errno_t set_endpoints(struct devicecode_ctx *dc_ctx,
|
|
const char *device_auth_endpoint,
|
|
const char *token_endpoint,
|
|
@@ -210,6 +261,7 @@ struct cli_opts {
|
|
const char *jwks_uri;
|
|
const char *scope;
|
|
const char *client_secret;
|
|
+ bool client_secret_stdin;
|
|
const char *ca_db;
|
|
const char *user_identifier_attr;
|
|
bool libcurl_debug;
|
|
@@ -253,6 +305,8 @@ static int parse_cli(int argc, const char *argv[], struct cli_opts *opts)
|
|
{"client-id", 0, POPT_ARG_STRING, &opts->client_id, 0, _("Client ID"), NULL},
|
|
{"client-secret", 0, POPT_ARG_STRING, &opts->client_secret, 0,
|
|
_("Client secret (if needed)"), NULL},
|
|
+ {"client-secret-stdin", 0, POPT_ARG_NONE, NULL, 's',
|
|
+ _("Read client secret from standard input"), NULL},
|
|
{"ca-db", 0, POPT_ARG_STRING, &opts->ca_db, 0,
|
|
_("Path to PEM file with CA certificates"), NULL},
|
|
{"libcurl-debug", 0, POPT_ARG_NONE, NULL, 'c',
|
|
@@ -280,6 +334,9 @@ static int parse_cli(int argc, const char *argv[], struct cli_opts *opts)
|
|
case 'c':
|
|
opts->libcurl_debug = true;
|
|
break;
|
|
+ case 's':
|
|
+ opts->client_secret_stdin = true;
|
|
+ break;
|
|
default:
|
|
fprintf(stderr, "\nInvalid option %s: %s\n\n",
|
|
poptBadOption(pc, 0), poptStrerror(opt));
|
|
@@ -324,6 +381,12 @@ static int parse_cli(int argc, const char *argv[], struct cli_opts *opts)
|
|
goto done;
|
|
}
|
|
|
|
+ if (opts->client_secret != NULL && opts->client_secret_stdin) {
|
|
+ fprintf(stderr, "\n--client-secret and --client-secret-stdin are "
|
|
+ "mutually exclusive.\n\n");
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
poptFreeContext(pc);
|
|
print_usage = false;
|
|
|
|
@@ -454,6 +517,15 @@ int main(int argc, const char *argv[])
|
|
}
|
|
|
|
if (opts.get_device_code) {
|
|
+ if (opts.client_secret_stdin) {
|
|
+ ret = read_client_secret_from_stdin(dc_ctx, &opts.client_secret);
|
|
+ if (ret != EOK) {
|
|
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
+ "Failed to read client secret from stdin.\n");
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+
|
|
ret = get_devicecode(dc_ctx, opts.client_id, opts.client_secret);
|
|
if (ret != EOK) {
|
|
DEBUG(SSSDBG_OP_FAILURE, "Failed to get device code.\n");
|
|
@@ -463,7 +535,10 @@ int main(int argc, const char *argv[])
|
|
|
|
if (opts.get_access_token) {
|
|
if (dc_ctx->device_code == NULL) {
|
|
- ret = read_device_code_from_stdin(dc_ctx);
|
|
+ ret = read_device_code_from_stdin(dc_ctx,
|
|
+ opts.client_secret_stdin
|
|
+ ? &opts.client_secret
|
|
+ : NULL);
|
|
if (ret != EOK) {
|
|
DEBUG(SSSDBG_OP_FAILURE,
|
|
"Failed to read device code from stdin.\n");
|
|
--
|
|
2.37.3
|
|
|