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