From ff941299cfc427f8ba2939d1950d8f954e3e3602 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 19 Jun 2021 15:41:18 +0100 Subject: [PATCH] Uppity: add stunt options for trivial authentication. This allows the 'no trivial auth' option introduced by the previous commit to be tested. Uppity has grown three new options to make it accept "none" authentication, keyboard-interactive involving no prompts, and the perverse sending of USERAUTH_SUCCESS after a signatureless public-key offer. The first of those options also enables the analogue in SSH-1; the other two have no SSH-1 analogues in the first place. (SSH-1 public key authentication has a challenge-response structure that doesn't contain any way to terminate the exchange early with success. And the TIS and CryptoCard methods, which are its closest analogue of k-i, have a fixed number of prompts, which is not 0.) --- ssh/login1-server.c | 5 +-- ssh/server.h | 3 ++ ssh/userauth2-server.c | 6 ++-- unix/uppity.c | 74 +++++++++++++++++++++++++++++------------- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/ssh/login1-server.c b/ssh/login1-server.c index 040342da..14f5edd6 100644 --- a/ssh/login1-server.c +++ b/ssh/login1-server.c @@ -39,7 +39,6 @@ struct ssh1_login_server_state { unsigned ap_methods, current_method; unsigned char auth_rsa_expected_response[16]; RSAKey *authkey; - bool auth_successful; PacketProtocolLayer ppl; }; @@ -267,7 +266,9 @@ static void ssh1_login_server_process_queue(PacketProtocolLayer *ppl) s->username.ptr = s->username_str = mkstr(s->username); ppl_logevent("Received username '%.*s'", PTRLEN_PRINTF(s->username)); - s->auth_successful = auth_none(s->authpolicy, s->username); + if (auth_none(s->authpolicy, s->username)) + goto auth_success; + while (1) { /* Signal failed authentication */ pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_SMSG_FAILURE); diff --git a/ssh/server.h b/ssh/server.h index 5cc393df..7a4f9e78 100644 --- a/ssh/server.h +++ b/ssh/server.h @@ -21,6 +21,9 @@ struct SshServerConfig { bool stunt_pretend_to_accept_any_pubkey; bool stunt_open_unconditional_agent_socket; + bool stunt_allow_none_auth; + bool stunt_allow_trivial_ki_auth; + bool stunt_return_success_to_pubkey_offer; }; Plug *ssh_server_plug( diff --git a/ssh/userauth2-server.c b/ssh/userauth2-server.c index da1e79c6..bfe258ce 100644 --- a/ssh/userauth2-server.c +++ b/ssh/userauth2-server.c @@ -209,7 +209,8 @@ static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl) if (!(s->methods & s->this_method)) goto failure; - has_signature = get_bool(pktin); + has_signature = get_bool(pktin) || + s->ssc->stunt_return_success_to_pubkey_offer; algorithm = get_string(pktin); blob = get_string(pktin); @@ -251,7 +252,8 @@ static void ssh2_userauth_server_process_queue(PacketProtocolLayer *ppl) signature = get_string(pktin); success = ssh_key_verify(key, signature, - ptrlen_from_strbuf(sigdata)); + ptrlen_from_strbuf(sigdata)) || + s->ssc->stunt_return_success_to_pubkey_offer; ssh_key_free(key); strbuf_free(sigdata); diff --git a/unix/uppity.c b/unix/uppity.c index 1a35451b..4189c7e0 100644 --- a/unix/uppity.c +++ b/unix/uppity.c @@ -110,6 +110,8 @@ void make_unix_sftp_filehandle_key(void *data, size_t size) static bool verbose; +struct server_config; + struct AuthPolicyShared { struct AuthPolicy_ssh1_pubkey *ssh1keys; struct AuthPolicy_ssh2_pubkey *ssh2keys; @@ -124,6 +126,24 @@ struct server_instance { unsigned id; AuthPolicy ap; LogPolicy logpolicy; + struct server_config *cfg; +}; + +struct server_config { + Conf *conf; + const SshServerConfig *ssc; + + ssh_key **hostkeys; + int nhostkeys; + + RSAKey *hostkey1; + + struct AuthPolicyShared *ap_shared; + + unsigned next_id; + + Socket *listening_socket; + Plug listening_plug; }; static void log_to_stderr(unsigned id, const char *msg) @@ -175,11 +195,21 @@ struct AuthPolicy_ssh2_pubkey { unsigned auth_methods(AuthPolicy *ap) { - return (AUTHMETHOD_PUBLICKEY | AUTHMETHOD_PASSWORD | AUTHMETHOD_KBDINT | - AUTHMETHOD_TIS | AUTHMETHOD_CRYPTOCARD); + struct server_instance *inst = container_of( + ap, struct server_instance, ap); + unsigned methods = (AUTHMETHOD_PUBLICKEY | AUTHMETHOD_PASSWORD | + AUTHMETHOD_KBDINT | AUTHMETHOD_TIS | + AUTHMETHOD_CRYPTOCARD); + if (inst->cfg->ssc->stunt_allow_none_auth) + methods |= AUTHMETHOD_NONE; + return methods; } bool auth_none(AuthPolicy *ap, ptrlen username) { + struct server_instance *inst = container_of( + ap, struct server_instance, ap); + if (inst->cfg->ssc->stunt_allow_none_auth) + return true; return false; } int auth_password(AuthPolicy *ap, ptrlen username, ptrlen password, @@ -249,13 +279,21 @@ AuthKbdInt *auth_kbdint_prompts(AuthPolicy *ap, ptrlen username) aki->prompts[1].prompt = dupstr("Silent prompt: "); aki->prompts[1].echo = false; return aki; - case 1: + case 1: { + struct server_instance *inst = container_of( + ap, struct server_instance, ap); aki = snew(AuthKbdInt); - aki->title = dupstr("Zero-prompt step"); - aki->instruction = dupstr("Shouldn't see any prompts this time"); + if (inst->cfg->ssc->stunt_allow_trivial_ki_auth) { + aki->title = dupstr(""); + aki->instruction = dupstr(""); + } else { + aki->title = dupstr("Zero-prompt step"); + aki->instruction = dupstr("Shouldn't see any prompts this time"); + } aki->nprompts = 0; aki->prompts = NULL; return aki; + } default: ap->kbdint_state = 0; return NULL; @@ -416,23 +454,6 @@ static bool longoptnoarg(const char *arg, const char *expected) return false; } -struct server_config { - Conf *conf; - const SshServerConfig *ssc; - - ssh_key **hostkeys; - int nhostkeys; - - RSAKey *hostkey1; - - struct AuthPolicyShared *ap_shared; - - unsigned next_id; - - Socket *listening_socket; - Plug listening_plug; -}; - static Plug *server_conn_plug( struct server_config *cfg, struct server_instance **inst_out) { @@ -442,7 +463,10 @@ static Plug *server_conn_plug( inst->id = cfg->next_id++; inst->ap.shared = cfg->ap_shared; + if (cfg->ssc->stunt_allow_trivial_ki_auth) + inst->ap.kbdint_state = 1; inst->logpolicy.vt = &server_logpolicy_vt; + inst->cfg = cfg; if (inst_out) *inst_out = inst; @@ -785,6 +809,12 @@ int main(int argc, char **argv) ssc.stunt_pretend_to_accept_any_pubkey = true; } else if (!strcmp(arg, "--open-unconditional-agent-socket")) { ssc.stunt_open_unconditional_agent_socket = true; + } else if (!strcmp(arg, "--allow-none-auth")) { + ssc.stunt_allow_none_auth = true; + } else if (!strcmp(arg, "--allow-trivial-ki-auth")) { + ssc.stunt_allow_trivial_ki_auth = true; + } else if (!strcmp(arg, "--return-success-to-pubkey-offer")) { + ssc.stunt_return_success_to_pubkey_offer = true; } else { fprintf(stderr, "%s: unrecognised option '%s'\n", appname, arg); exit(1);