Skip to content

Commit

Permalink
add ssh keyboard interactive authentication
Browse files Browse the repository at this point in the history
Supporting keyboard-interactive authentication enables login with Cisco
DUO MFA (#2).
  • Loading branch information
upa committed Mar 31, 2024
1 parent 262a715 commit 9b8ba69
Showing 1 changed file with 57 additions and 1 deletion.
58 changes: 57 additions & 1 deletion src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <strerrno.h>

static int ssh_verify_known_hosts(ssh_session session);
static int ssh_authenticate_kbdint(ssh_session session);

static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
{
Expand Down Expand Up @@ -100,17 +101,18 @@ static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts)
return 0;

auth_bit_mask = ssh_userauth_list(ssh, NULL);

if (auth_bit_mask & SSH_AUTH_METHOD_NONE &&
ssh_userauth_none(ssh, NULL) == SSH_AUTH_SUCCESS)
return 0;

auth_bit_mask = ssh_userauth_list(ssh, NULL);
if (auth_bit_mask & SSH_AUTH_METHOD_PUBLICKEY) {
char *p = opts->passphrase ? opts->passphrase : NULL;
if (ssh_userauth_publickey_auto(ssh, NULL, p) == SSH_AUTH_SUCCESS)
return 0;
}

auth_bit_mask = ssh_userauth_list(ssh, NULL);
if (auth_bit_mask & SSH_AUTH_METHOD_PASSWORD) {
if (!opts->password) {
char buf[128] = {};
Expand All @@ -128,6 +130,12 @@ static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts)
return 0;
}

auth_bit_mask = ssh_userauth_list(ssh, NULL);
if (auth_bit_mask & SSH_AUTH_METHOD_INTERACTIVE) {
if (ssh_authenticate_kbdint(ssh) == SSH_AUTH_SUCCESS)
return 0;
}

return -1;
}

Expand Down Expand Up @@ -319,6 +327,54 @@ static int ssh_verify_known_hosts(ssh_session session)
return 0;
}

static int ssh_authenticate_kbdint(ssh_session ssh)
{
/* Copied and bit modified from
* https://api.libssh.org/stable/libssh_tutor_authentication.html */
int rc;

rc = ssh_userauth_kbdint(ssh, NULL, NULL);
while (rc == SSH_AUTH_INFO) {
const char *name, *instruction;
int nprompts, iprompt;

name = ssh_userauth_kbdint_getname(ssh);
instruction = ssh_userauth_kbdint_getinstruction(ssh);
nprompts = ssh_userauth_kbdint_getnprompts(ssh);

if (strlen(name) > 0)
printf("%s\n", name);
if (strlen(instruction) > 0)
printf("%s\n", instruction);
for (iprompt = 0; iprompt < nprompts; iprompt++) {
const char *prompt;
char echo;

prompt = ssh_userauth_kbdint_getprompt(ssh, iprompt, &echo);
if (echo) {
char buf[128], *ptr;

printf("%s", prompt);
if (fgets(buf, sizeof(buf), stdin) == NULL)
return SSH_AUTH_ERROR;
buf[sizeof(buf) - 1] = '\0';
if ((ptr = strchr(buf, '\n')) != NULL)
*ptr = '\0';
if (ssh_userauth_kbdint_setanswer(ssh, iprompt, buf) < 0)
return SSH_AUTH_ERROR;
memset(buf, 0, strlen(buf));
} else {
char *ptr;
ptr = getpass(prompt);
if (ssh_userauth_kbdint_setanswer(ssh, iprompt, ptr) < 0)
return SSH_AUTH_ERROR;
}
}
rc = ssh_userauth_kbdint(ssh, NULL, NULL);
}
return rc;
}

void ssh_sftp_close(sftp_session sftp)
{
ssh_session ssh = sftp_ssh(sftp);
Expand Down

0 comments on commit 9b8ba69

Please sign in to comment.