1
1

options: Add option to set server accepted pubkey types

The added option SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES allows
restricting the allowed public key types accepted by the server for
authentication.

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Этот коммит содержится в:
Anderson Toshiyuki Sasaki 2019-05-15 11:48:49 +02:00 коммит произвёл Andreas Schneider
родитель bc95a51710
Коммит f4363f5655
7 изменённых файлов: 136 добавлений и 11 удалений

Просмотреть файл

@ -48,6 +48,7 @@ struct ssh_bind_struct {
int toaccept; int toaccept;
bool config_processed; bool config_processed;
char *config_dir; char *config_dir;
char *pubkey_accepted_key_types;
}; };
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct

Просмотреть файл

@ -53,6 +53,7 @@ enum ssh_bind_options_e {
SSH_BIND_OPTIONS_HMAC_C_S, SSH_BIND_OPTIONS_HMAC_C_S,
SSH_BIND_OPTIONS_HMAC_S_C, SSH_BIND_OPTIONS_HMAC_S_C,
SSH_BIND_OPTIONS_CONFIG_DIR, SSH_BIND_OPTIONS_CONFIG_DIR,
SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
}; };
typedef struct ssh_bind_struct* ssh_bind; typedef struct ssh_bind_struct* ssh_bind;

Просмотреть файл

@ -38,6 +38,7 @@
#include "libssh/buffer.h" #include "libssh/buffer.h"
#include "libssh/socket.h" #include "libssh/socket.h"
#include "libssh/session.h" #include "libssh/session.h"
#include "libssh/token.h"
/** /**
* @addtogroup libssh_server * @addtogroup libssh_server
@ -402,6 +403,7 @@ void ssh_bind_free(ssh_bind sshbind){
SAFE_FREE(sshbind->banner); SAFE_FREE(sshbind->banner);
SAFE_FREE(sshbind->bindaddr); SAFE_FREE(sshbind->bindaddr);
SAFE_FREE(sshbind->config_dir); SAFE_FREE(sshbind->config_dir);
SAFE_FREE(sshbind->pubkey_accepted_key_types);
SAFE_FREE(sshbind->dsakey); SAFE_FREE(sshbind->dsakey);
SAFE_FREE(sshbind->rsakey); SAFE_FREE(sshbind->rsakey);
@ -456,6 +458,29 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
} }
} }
if (sshbind->pubkey_accepted_key_types != NULL) {
if (session->opts.pubkey_accepted_types == NULL) {
session->opts.pubkey_accepted_types = strdup(sshbind->pubkey_accepted_key_types);
if (session->opts.pubkey_accepted_types == NULL) {
ssh_set_error_oom(sshbind);
return SSH_ERROR;
}
} else {
char *p;
/* If something was set to the session prior to calling this
* function, keep only what is allowed by the options set in
* sshbind */
p = ssh_find_all_matching(sshbind->pubkey_accepted_key_types,
session->opts.pubkey_accepted_types);
if (p == NULL) {
return SSH_ERROR;
}
SAFE_FREE(session->opts.pubkey_accepted_types);
session->opts.pubkey_accepted_types = p;
}
}
session->common.log_verbosity = sshbind->common.log_verbosity; session->common.log_verbosity = sshbind->common.log_verbosity;
if(sshbind->banner != NULL) if(sshbind->banner != NULL)
session->opts.custombanner = strdup(sshbind->banner); session->opts.custombanner = strdup(sshbind->banner);

Просмотреть файл

@ -868,11 +868,28 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
msg->auth_request.pubkey, msg->auth_request.pubkey,
&sig); &sig);
if (rc == SSH_OK) { if (rc == SSH_OK) {
rc = ssh_pki_signature_verify(session, /* Check if the signature from client matches server preferences */
sig, if (session->opts.pubkey_accepted_types) {
msg->auth_request.pubkey, if (!ssh_match_group(session->opts.pubkey_accepted_types,
ssh_buffer_get(digest), sig->type_c))
ssh_buffer_get_len(digest)); {
ssh_set_error(session,
SSH_FATAL,
"Public key from client (%s) doesn't match server "
"preference (%s)",
sig->type_c,
session->opts.pubkey_accepted_types);
rc = SSH_ERROR;
}
}
if (rc == SSH_OK) {
rc = ssh_pki_signature_verify(session,
sig,
msg->auth_request.pubkey,
ssh_buffer_get(digest),
ssh_buffer_get_len(digest));
}
} }
ssh_string_free(sig_blob); ssh_string_free(sig_blob);
ssh_buffer_free(digest); ssh_buffer_free(digest);

Просмотреть файл

@ -1608,6 +1608,10 @@ static int ssh_bind_set_algo(ssh_bind sshbind,
* paths of configuration files to * paths of configuration files to
* ssh_bind_options_parse_config(). * ssh_bind_options_parse_config().
* *
* - SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES:
* Set the public key algorithm accepted by the server
* (const char *, comma-separated list).
*
* @param value The value to set. This is a generic pointer and the * @param value The value to set. This is a generic pointer and the
* datatype which should be used is described at the * datatype which should be used is described at the
* corresponding value of type above. * corresponding value of type above.
@ -1912,6 +1916,24 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
} }
} }
break; break;
case SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES:
v = value;
if (v == NULL || v[0] == '\0') {
ssh_set_error_invalid(sshbind);
return -1;
} else {
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
if (p == NULL) {
ssh_set_error(sshbind, SSH_REQUEST_DENIED,
"Setting method: no known public key algorithm (%s)",
v);
return -1;
}
SAFE_FREE(sshbind->pubkey_accepted_key_types);
sshbind->pubkey_accepted_key_types = p;
}
break;
default: default:
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1; return -1;

Просмотреть файл

@ -180,11 +180,14 @@ static int ssh_server_send_extensions(ssh_session session) {
const char *hostkey_algorithms; const char *hostkey_algorithms;
SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO"); SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO");
/*
* We can list here all the default hostkey methods, since if (session->opts.pubkey_accepted_types) {
* they already contain the SHA2 extension algorithms hostkey_algorithms = session->opts.pubkey_accepted_types;
*/ } else {
hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS); /* There are no restrictions to the accepted public keys */
hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS);
}
rc = ssh_buffer_pack(session->out_buffer, rc = ssh_buffer_pack(session->out_buffer,
"bdss", "bdss",
SSH2_MSG_EXT_INFO, SSH2_MSG_EXT_INFO,

Просмотреть файл

@ -1358,6 +1358,60 @@ static void torture_bind_options_config_dir(void **state)
assert_string_equal(bind->config_dir, replacement_dir); assert_string_equal(bind->config_dir, replacement_dir);
} }
static void torture_bind_options_set_pubkey_accepted_key_types(void **state)
{
struct bind_st *test_state;
ssh_bind bind;
int rc;
assert_non_null(state);
test_state = *((struct bind_st **)state);
assert_non_null(test_state);
assert_non_null(test_state->bind);
bind = test_state->bind;
/* Test known Pubkey Types */
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
assert_int_equal(rc, 0);
assert_non_null(bind->pubkey_accepted_key_types);
assert_string_equal(bind->pubkey_accepted_key_types,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
SAFE_FREE(bind->pubkey_accepted_key_types);
/* Test with some unknown type */
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
"ssh-ed25519,ecdsa-sha2-nistp384,unknown-type,ssh-rsa");
assert_int_equal(rc, 0);
assert_non_null(bind->pubkey_accepted_key_types);
assert_string_equal(bind->pubkey_accepted_key_types,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
SAFE_FREE(bind->pubkey_accepted_key_types);
/* Test with only unknown type */
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
"unknown-type");
assert_int_equal(rc, -1);
assert_null(bind->pubkey_accepted_key_types);
/* Test with something set and then try unknown type */
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
assert_int_equal(rc, 0);
assert_non_null(bind->pubkey_accepted_key_types);
assert_string_equal(bind->pubkey_accepted_key_types,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES,
"unknown-type");
assert_int_equal(rc, -1);
/* Check that nothing changed */
assert_non_null(bind->pubkey_accepted_key_types);
assert_string_equal(bind->pubkey_accepted_key_types,
"ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa");
}
#endif /* WITH_SERVER */ #endif /* WITH_SERVER */
@ -1387,7 +1441,7 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_options_copy, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_copy, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown),
cmocka_unit_test_setup_teardown(torture_options_config_match, cmocka_unit_test_setup_teardown(torture_options_config_match,
setup, teardown) setup, teardown),
}; };
#ifdef WITH_SERVER #ifdef WITH_SERVER
@ -1428,6 +1482,8 @@ int torture_run_tests(void) {
sshbind_setup, sshbind_teardown), sshbind_setup, sshbind_teardown),
cmocka_unit_test_setup_teardown(torture_bind_options_config_dir, cmocka_unit_test_setup_teardown(torture_bind_options_config_dir,
sshbind_setup, sshbind_teardown), sshbind_setup, sshbind_teardown),
cmocka_unit_test_setup_teardown(torture_bind_options_set_pubkey_accepted_key_types,
sshbind_setup, sshbind_teardown),
}; };
#endif /* WITH_SERVER */ #endif /* WITH_SERVER */