Two-factor authentication support (pubkey and password)

This commit is contained in:
Jackkal 2022-04-29 15:43:15 +02:00
parent 46654cda85
commit 0c9318a0b2
6 changed files with 59 additions and 18 deletions

View File

@ -53,6 +53,10 @@ Disable password logins.
.B \-g .B \-g
Disable password logins for root. Disable password logins for root.
.TP .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 .B \-j
Disable local port forwarding. Disable local port forwarding.
.TP .TP

View File

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

View File

@ -278,11 +278,21 @@ void svr_auth_pam(int valid_user) {
goto cleanup; goto cleanup;
} }
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 auth succeeded for '%s' from %s, extra auth required",
ses.authstate.pw_name,
svr_ses.addrstring);
ses.authstate.authtypes &= ~AUTH_TYPE_PASSWORD;
send_msg_userauth_failure(1, 0); /* Send partial success */
} else {
/* successful authentication */ /* successful authentication */
dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s", dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s",
ses.authstate.pw_name, ses.authstate.pw_name,
svr_ses.addrstring); svr_ses.addrstring);
send_msg_userauth_success(); send_msg_userauth_success();
}
cleanup: cleanup:
if (password != NULL) { if (password != NULL) {

View File

@ -106,12 +106,22 @@ void svr_auth_password(int valid_user) {
} }
if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) { if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
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;
send_msg_userauth_failure(1, 0); /* Send partial success */
} else {
/* successful authentication */ /* successful authentication */
dropbear_log(LOG_NOTICE, dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s", "Password auth succeeded for '%s' from %s",
ses.authstate.pw_name, ses.authstate.pw_name,
svr_ses.addrstring); svr_ses.addrstring);
send_msg_userauth_success(); send_msg_userauth_success();
}
} else { } else {
dropbear_log(LOG_WARNING, dropbear_log(LOG_WARNING,
"Bad password attempt for '%s' from %s", "Bad password attempt for '%s' from %s",

View File

@ -64,6 +64,7 @@
#include "ssh.h" #include "ssh.h"
#include "packet.h" #include "packet.h"
#include "algo.h" #include "algo.h"
#include "runopts.h"
#if DROPBEAR_SVR_PUBKEY_AUTH #if DROPBEAR_SVR_PUBKEY_AUTH
@ -201,12 +202,22 @@ void svr_auth_pubkey(int valid_user) {
/* ... and finally verify the signature */ /* ... and finally verify the signature */
fp = sign_key_fingerprint(keyblob, keybloblen); fp = sign_key_fingerprint(keyblob, keybloblen);
if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) { if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) {
if (svr_opts.multiauthmethod && (ses.authstate.authtypes & ~AUTH_TYPE_PUBKEY)) {
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 {
dropbear_log(LOG_NOTICE, dropbear_log(LOG_NOTICE,
"Pubkey auth succeeded for '%s' with %s key %s from %s", "Pubkey auth succeeded for '%s' with %s key %s from %s",
ses.authstate.pw_name, ses.authstate.pw_name,
signkey_name_from_type(keytype, NULL), fp, signkey_name_from_type(keytype, NULL), fp,
svr_ses.addrstring); svr_ses.addrstring);
send_msg_userauth_success(); send_msg_userauth_success();
}
#if DROPBEAR_PLUGIN #if DROPBEAR_PLUGIN
if ((ses.plugin_session != NULL) && (svr_ses.plugin_instance->auth_success != NULL)) { 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 */ /* 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" "-s Disable password logins\n"
"-g Disable password logins for root\n" "-g Disable password logins for root\n"
"-B Allow blank password logins\n" "-B Allow blank password logins\n"
"-t Enable two-factor authentication (both password and public key required)\n"
#endif #endif
"-T Maximum authentication tries (default %d)\n" "-T Maximum authentication tries (default %d)\n"
#if DROPBEAR_SVR_LOCALTCPFWD #if DROPBEAR_SVR_LOCALTCPFWD
@ -158,6 +159,7 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.noauthpass = 0; svr_opts.noauthpass = 0;
svr_opts.norootpass = 0; svr_opts.norootpass = 0;
svr_opts.allowblankpass = 0; svr_opts.allowblankpass = 0;
svr_opts.multiauthmethod = 0;
svr_opts.maxauthtries = MAX_AUTH_TRIES; svr_opts.maxauthtries = MAX_AUTH_TRIES;
svr_opts.inetdmode = 0; svr_opts.inetdmode = 0;
svr_opts.portcount = 0; svr_opts.portcount = 0;
@ -295,6 +297,9 @@ void svr_getopts(int argc, char ** argv) {
case 'B': case 'B':
svr_opts.allowblankpass = 1; svr_opts.allowblankpass = 1;
break; break;
case 't':
svr_opts.multiauthmethod = 1;
break;
#endif #endif
case 'h': case 'h':
printhelp(argv[0]); printhelp(argv[0]);