Merge pull request #160 from Jackkal/two-factor-authentication

Two-factor authentication support (pubkey and password)
This commit is contained in:
Matt Johnston 2022-11-09 17:33:48 +08:00
commit 71d78653c7
6 changed files with 66 additions and 18 deletions

View File

@ -53,6 +53,10 @@ Disable password logins.
.B \-g
Disable password logins for root.
.TP
.B \-t
Enable two-factor authentication. Both password login and public key authentication are
required. Should not be used with the '-s' option.
.TP
.B \-j
Disable local port forwarding.
.TP

View File

@ -106,6 +106,7 @@ typedef struct svr_runopts {
int noauthpass;
int norootpass;
int allowblankpass;
int multiauthmethod;
unsigned int maxauthtries;
#if DROPBEAR_SVR_REMOTETCPFWD

View File

@ -30,6 +30,7 @@
#include "buffer.h"
#include "dbutil.h"
#include "auth.h"
#include "runopts.h"
#if DROPBEAR_SVR_PAM_AUTH
@ -278,12 +279,22 @@ void svr_auth_pam(int valid_user) {
goto cleanup;
}
/* successful authentication */
dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s",
ses.authstate.pw_name,
svr_ses.addrstring);
send_msg_userauth_success();
if (svr_opts.multiauthmethod && (ses.authstate.authtypes & ~AUTH_TYPE_PASSWORD)) {
/* successful PAM password authentication, but extra auth required */
dropbear_log(LOG_NOTICE,
"PAM password auth succeeded for '%s' from %s, extra auth required",
ses.authstate.pw_name,
svr_ses.addrstring);
ses.authstate.authtypes &= ~AUTH_TYPE_PASSWORD; /* PAM password auth ok, delete the method flag */
send_msg_userauth_failure(1, 0); /* Send partial success */
} else {
/* successful authentication */
dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s",
ses.authstate.pw_name,
svr_ses.addrstring);
send_msg_userauth_success();
}
cleanup:
if (password != NULL) {
m_burn(password, passwordlen);

View File

@ -106,12 +106,22 @@ void svr_auth_password(int valid_user) {
}
if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
/* successful authentication */
dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s",
ses.authstate.pw_name,
svr_ses.addrstring);
send_msg_userauth_success();
if (svr_opts.multiauthmethod && (ses.authstate.authtypes & ~AUTH_TYPE_PASSWORD)) {
/* successful password authentication, but extra auth required */
dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s, extra auth required",
ses.authstate.pw_name,
svr_ses.addrstring);
ses.authstate.authtypes &= ~AUTH_TYPE_PASSWORD; /* password auth ok, delete the method flag */
send_msg_userauth_failure(1, 0); /* Send partial success */
} else {
/* successful authentication */
dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s",
ses.authstate.pw_name,
svr_ses.addrstring);
send_msg_userauth_success();
}
} else {
dropbear_log(LOG_WARNING,
"Bad password attempt for '%s' from %s",

View File

@ -64,6 +64,7 @@
#include "ssh.h"
#include "packet.h"
#include "algo.h"
#include "runopts.h"
#if DROPBEAR_SVR_PUBKEY_AUTH
@ -211,12 +212,24 @@ void svr_auth_pubkey(int valid_user) {
/* ... and finally verify the signature */
fp = sign_key_fingerprint(keyblob, keybloblen);
if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) {
dropbear_log(LOG_NOTICE,
"Pubkey auth succeeded for '%s' with %s key %s from %s",
ses.authstate.pw_name,
signkey_name_from_type(keytype, NULL), fp,
svr_ses.addrstring);
send_msg_userauth_success();
if (svr_opts.multiauthmethod && (ses.authstate.authtypes & ~AUTH_TYPE_PUBKEY)) {
/* successful pubkey authentication, but extra auth required */
dropbear_log(LOG_NOTICE,
"Pubkey auth succeeded for '%s' with %s key %s from %s, extra auth required",
ses.authstate.pw_name,
signkey_name_from_type(keytype, NULL), fp,
svr_ses.addrstring);
ses.authstate.authtypes &= ~AUTH_TYPE_PUBKEY; /* pubkey auth ok, delete the method flag */
send_msg_userauth_failure(1, 0); /* Send partial success */
} else {
/* successful authentication */
dropbear_log(LOG_NOTICE,
"Pubkey auth succeeded for '%s' with %s key %s from %s",
ses.authstate.pw_name,
signkey_name_from_type(keytype, NULL), fp,
svr_ses.addrstring);
send_msg_userauth_success();
}
#if DROPBEAR_PLUGIN
if ((ses.plugin_session != NULL) && (svr_ses.plugin_instance->auth_success != NULL)) {
/* Was authenticated through the external plugin. tell plugin that signature verification was ok */

View File

@ -81,6 +81,7 @@ static void printhelp(const char * progname) {
"-s Disable password logins\n"
"-g Disable password logins for root\n"
"-B Allow blank password logins\n"
"-t Enable two-factor authentication (both password and public key required)\n"
#endif
"-T Maximum authentication tries (default %d)\n"
#if DROPBEAR_SVR_LOCALTCPFWD
@ -159,6 +160,7 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.noauthpass = 0;
svr_opts.norootpass = 0;
svr_opts.allowblankpass = 0;
svr_opts.multiauthmethod = 0;
svr_opts.maxauthtries = MAX_AUTH_TRIES;
svr_opts.inetdmode = 0;
svr_opts.portcount = 0;
@ -297,6 +299,9 @@ void svr_getopts(int argc, char ** argv) {
case 'B':
svr_opts.allowblankpass = 1;
break;
case 't':
svr_opts.multiauthmethod = 1;
break;
#endif
case 'h':
printhelp(argv[0]);
@ -447,6 +452,10 @@ void svr_getopts(int argc, char ** argv) {
}
#endif
if (svr_opts.multiauthmethod && svr_opts.noauthpass) {
dropbear_exit("-t and -s are incompatible");
}
#if DROPBEAR_PLUGIN
if (pubkey_plugin) {
svr_opts.pubkey_plugin = m_strdup(pubkey_plugin);