Implement no-touch-required and verify-requred for authorized_keys file

This commit is contained in:
Egor Duda 2022-06-11 13:35:06 +03:00
parent 544f28a051
commit 62ea53c1e5
No known key found for this signature in database
GPG Key ID: 8610EBBBC18A37F1
9 changed files with 57 additions and 10 deletions

4
auth.h
View File

@ -139,6 +139,10 @@ struct PubKeyOptions {
int no_pty_flag; int no_pty_flag;
/* "command=" option. */ /* "command=" option. */
char * forced_command; char * forced_command;
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
int no_touch_required_flag;
int verify_required_flag;
#endif
}; };
#endif #endif

View File

@ -688,7 +688,7 @@ int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype,
if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) { if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) {
ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype); ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype);
if (eck && *eck) { if (eck && *eck) {
return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen); return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen, key->sk_flags_mask);
} }
} }
#endif #endif
@ -696,7 +696,7 @@ int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype,
if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) { if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) {
dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype); dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype);
if (eck && *eck) { if (eck && *eck) {
return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen); return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen, key->sk_flags_mask);
} }
} }
#endif #endif

View File

@ -127,6 +127,7 @@ struct SIGN_key {
/* application ID for U2F/FIDO key types, a malloced string */ /* application ID for U2F/FIDO key types, a malloced string */
char * sk_app; char * sk_app;
unsigned int sk_applen; unsigned int sk_applen;
unsigned char sk_flags_mask;
#endif #endif
}; };

View File

@ -8,7 +8,9 @@
#include "sk-ecdsa.h" #include "sk-ecdsa.h"
#include "ssh.h" #include "ssh.h"
int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf, const char* app, unsigned int applen) { int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf,
const char* app, unsigned int applen,
unsigned char sk_flags_mask) {
hash_state hs; hash_state hs;
unsigned char subhash[SHA256_HASH_SIZE]; unsigned char subhash[SHA256_HASH_SIZE];
buffer *sk_buffer = NULL, *sig_buffer = NULL; buffer *sk_buffer = NULL, *sig_buffer = NULL;
@ -41,13 +43,18 @@ int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf,
buf_free(sk_buffer); buf_free(sk_buffer);
buf_free(sig_buffer); buf_free(sig_buffer);
/* TODO: allow "no-touch-required" or "verify-required" authorized_keys options */ if (~flags & sk_flags_mask & SSH_SK_USER_PRESENCE_REQD) {
if (!(flags & SSH_SK_USER_PRESENCE_REQD)) {
if (ret == DROPBEAR_SUCCESS) { if (ret == DROPBEAR_SUCCESS) {
dropbear_log(LOG_WARNING, "Rejecting, user-presence not set"); dropbear_log(LOG_WARNING, "Rejecting, user-presence not set");
} }
ret = DROPBEAR_FAILURE; ret = DROPBEAR_FAILURE;
} }
if (~flags & sk_flags_mask & SSH_SK_USER_VERIFICATION_REQD) {
if (ret == DROPBEAR_SUCCESS) {
dropbear_log(LOG_WARNING, "Rejecting, user-verification not set");
}
ret = DROPBEAR_FAILURE;
}
TRACE(("leave buf_sk_ecdsa_verify, ret=%d", ret)) TRACE(("leave buf_sk_ecdsa_verify, ret=%d", ret))
return ret; return ret;

View File

@ -8,7 +8,9 @@
#include "buffer.h" #include "buffer.h"
#include "signkey.h" #include "signkey.h"
int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf, const char* app, unsigned int applen); int buf_sk_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf,
const char* app, unsigned int applen,
unsigned char sk_flags_mask);
#endif #endif

View File

@ -8,7 +8,9 @@
#include "ed25519.h" #include "ed25519.h"
#include "ssh.h" #include "ssh.h"
int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf, const char* app, unsigned int applen) { int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf,
const char* app, unsigned int applen,
unsigned char sk_flags_mask) {
int ret = DROPBEAR_FAILURE; int ret = DROPBEAR_FAILURE;
unsigned char *s; unsigned char *s;
@ -52,13 +54,18 @@ int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const bu
ret = DROPBEAR_SUCCESS; ret = DROPBEAR_SUCCESS;
} }
/* TODO: allow "no-touch-required" or "verify-required" authorized_keys options */ if (~flags & sk_flags_mask & SSH_SK_USER_PRESENCE_REQD) {
if (!(flags & SSH_SK_USER_PRESENCE_REQD)) {
if (ret == DROPBEAR_SUCCESS) { if (ret == DROPBEAR_SUCCESS) {
dropbear_log(LOG_WARNING, "Rejecting, user-presence not set"); dropbear_log(LOG_WARNING, "Rejecting, user-presence not set");
} }
ret = DROPBEAR_FAILURE; ret = DROPBEAR_FAILURE;
} }
if (~flags & sk_flags_mask & SSH_SK_USER_VERIFICATION_REQD) {
if (ret == DROPBEAR_SUCCESS) {
dropbear_log(LOG_WARNING, "Rejecting, user-verification not set");
}
ret = DROPBEAR_FAILURE;
}
out: out:
buf_free(sk_buffer); buf_free(sk_buffer);
TRACE(("leave buf_sk_ed25519_verify: ret %d", ret)) TRACE(("leave buf_sk_ed25519_verify: ret %d", ret))

View File

@ -8,7 +8,9 @@
#include "buffer.h" #include "buffer.h"
#include "ed25519.h" #include "ed25519.h"
int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf, const char* app, unsigned int applen); int buf_sk_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf,
const char* app, unsigned int applen,
unsigned char sk_flags_mask);
#endif #endif

View File

@ -182,6 +182,16 @@ void svr_auth_pubkey(int valid_user) {
goto out; goto out;
} }
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
key->sk_flags_mask = SSH_SK_USER_PRESENCE_REQD;
if (ses.authstate.pubkey_options && ses.authstate.pubkey_options->no_touch_required_flag) {
key->sk_flags_mask &= ~SSH_SK_USER_PRESENCE_REQD;
}
if (ses.authstate.pubkey_options && ses.authstate.pubkey_options->verify_required_flag) {
key->sk_flags_mask |= SSH_SK_USER_VERIFICATION_REQD;
}
#endif
/* create the data which has been signed - this a string containing /* create the data which has been signed - this a string containing
* session_id, concatenated with the payload packet up to the signature */ * session_id, concatenated with the payload packet up to the signature */
assert(ses.payload_beginning <= ses.payload->pos); assert(ses.payload_beginning <= ses.payload->pos);

View File

@ -205,6 +205,20 @@ int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filena
dropbear_log(LOG_WARNING, "Badly formatted command= authorized_keys option"); dropbear_log(LOG_WARNING, "Badly formatted command= authorized_keys option");
goto bad_option; goto bad_option;
} }
if (match_option(options_buf, "no-touch-required") == DROPBEAR_SUCCESS) {
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
dropbear_log(LOG_WARNING, "No user presence check required for U2F/FIDO key.");
ses.authstate.pubkey_options->no_touch_required_flag = 1;
#endif
goto next_option;
}
if (match_option(options_buf, "verify-required") == DROPBEAR_SUCCESS) {
#if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519
dropbear_log(LOG_WARNING, "User verification required for U2F/FIDO key.");
ses.authstate.pubkey_options->verify_required_flag = 1;
#endif
goto next_option;
}
next_option: next_option:
/* /*