copy_fail_family: skip DIRTYFAIL typed prompt under --i-know
The vendored DIRTYFAIL exploits call typed_confirm("DIRTYFAIL"), which
reads stdin interactively. SKELETONKEY already gates --exploit/--auto
behind --i-know, so the prompt is redundant and deadlocks non-interactive
runs like `skeletonkey --auto --i-know`.
Add a dirtyfail_assume_yes flag, forwarded from skeletonkey_ctx.authorized
by the bridge layer's apply_ctx(). When set, typed_confirm() auto-satisfies
its gate and logs that it did so.
The YES_BREAK_SSH self-lockout guard is exempt — it protects the
operator's own access rather than gating authorization, so it still
requires an interactive answer.
Standalone DIRTYFAIL builds are unchanged: the flag defaults false.
This commit is contained in:
@@ -33,6 +33,12 @@ static void apply_ctx(const struct skeletonkey_ctx *ctx)
|
||||
dirtyfail_use_color = !ctx->no_color;
|
||||
dirtyfail_active_probes = ctx->active_probe;
|
||||
dirtyfail_json = ctx->json;
|
||||
/* Forward the --i-know authorization gate. SKELETONKEY already
|
||||
* blocks --exploit/--auto unless --i-know is passed, so by the time
|
||||
* a DIRTYFAIL exploit callback runs, authorization is established.
|
||||
* This lets typed_confirm() skip its (now redundant) interactive
|
||||
* prompt, which otherwise deadlocks `skeletonkey --auto --i-know`. */
|
||||
dirtyfail_assume_yes = ctx->authorized;
|
||||
/* dirtyfail_no_revert is intentionally not driven from ctx —
|
||||
* it's a debug knob; default stays off. */
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ bool dirtyfail_use_color = true;
|
||||
bool dirtyfail_active_probes = false;
|
||||
bool dirtyfail_no_revert = false;
|
||||
bool dirtyfail_json = false;
|
||||
bool dirtyfail_assume_yes = false;
|
||||
|
||||
static void vlog(FILE *out, const char *prefix, const char *color,
|
||||
const char *fmt, va_list ap)
|
||||
@@ -226,6 +227,19 @@ size_t build_authenc_keyblob(unsigned char *out,
|
||||
|
||||
bool typed_confirm(const char *expected)
|
||||
{
|
||||
/* When the caller has already cleared an explicit authorization gate
|
||||
* (SKELETONKEY's --i-know, forwarded via dirtyfail_assume_yes), the
|
||||
* DIRTYFAIL typed prompt is redundant and would deadlock non-interactive
|
||||
* runs like `skeletonkey --auto --i-know`. Auto-satisfy it.
|
||||
*
|
||||
* The SSH self-lockout guard (YES_BREAK_SSH) is deliberately exempt:
|
||||
* it protects the operator's own access rather than gating
|
||||
* authorization, so it always requires an interactive answer. */
|
||||
if (dirtyfail_assume_yes && strcmp(expected, "YES_BREAK_SSH") != 0) {
|
||||
log_step("confirmation gate '%s' auto-satisfied (--i-know)", expected);
|
||||
return true;
|
||||
}
|
||||
|
||||
char buf[128];
|
||||
printf(" Type \033[1;33m%s\033[0m and press enter to proceed: ", expected);
|
||||
fflush(stdout);
|
||||
|
||||
@@ -86,6 +86,14 @@ extern bool dirtyfail_no_revert;
|
||||
* is redirected to stderr. Set by --json. */
|
||||
extern bool dirtyfail_json;
|
||||
|
||||
/* When true, typed_confirm() auto-satisfies its gate instead of reading
|
||||
* stdin — the caller has already cleared an explicit authorization gate.
|
||||
* SKELETONKEY's bridge layer sets this from skeletonkey_ctx.authorized
|
||||
* (i.e. the --i-know flag) so non-interactive runs like
|
||||
* `skeletonkey --auto --i-know` don't deadlock on the DIRTYFAIL prompt.
|
||||
* The YES_BREAK_SSH self-lockout guard is exempt — see typed_confirm(). */
|
||||
extern bool dirtyfail_assume_yes;
|
||||
|
||||
void log_step (const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
void log_ok (const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
void log_bad (const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
Reference in New Issue
Block a user