Skip to content

Commit 127f1ec

Browse files
romanmichalvasko
authored andcommitted
session server ssh BUGFIX partial auth methods
Require the client to authenticate via all of his configured auth methods, previously only the count of successes mattered. Fixes CESNET/netopeer2#1629
1 parent 22684e6 commit 127f1ec

2 files changed

Lines changed: 31 additions & 27 deletions

File tree

src/session_p.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,10 @@ struct nc_keystore {
158158
* @brief Tracks the state of a client's authentication.
159159
*/
160160
struct nc_auth_state {
161-
int auth_method_count; /**< The number of auth. methods that the user supports. */
162-
int auth_success_count; /**< The number of auth. methods that ended successfully. */
161+
int methods; /**< Bit field of authentication methods that the user supports. */
162+
int method_count; /**< Number of authentication methods that the user supports. */
163+
int success_methods; /**< Bit field of authentication methods that the user successfully authenticated with. */
164+
int success_count; /**< Number of authentication methods that the user successfully authenticated with. */
163165
};
164166

165167
/**
@@ -1129,10 +1131,10 @@ int nc_accept_ssh_session(struct nc_session *session, struct nc_server_ssh_opts
11291131
* @param[in] session Session structure of the connection.
11301132
* @param[in] opts Endpoint SSH options on which the session was created.
11311133
* @param[in] msg SSH message itself.
1132-
* @param[in] state State of the authentication.
1134+
* @param[in] auth_state State of the authentication.
11331135
* @return 0 if the message was handled, 1 if it is left up to libssh.
11341136
*/
1135-
int nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message msg, struct nc_auth_state *state);
1137+
int nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message msg, struct nc_auth_state *auth_state);
11361138

11371139
void nc_client_ssh_destroy_opts(void);
11381140
void _nc_client_ssh_destroy_opts(struct nc_client_ssh_opts *opts);

src/session_server_ssh.c

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,15 +1438,15 @@ nc_server_ssh_channel_subsystem(struct nc_session *session, ssh_channel channel,
14381438
* @param[in] method Type of the authentication method.
14391439
* @param[in] str_method String representation of the authentication method.
14401440
* @param[in] local_users_supported Whether the server supports local users.
1441-
* @param[in,out] state Authentication state.
1441+
* @param[in,out] auth_state Authentication state.
14421442
* @return 1 in case of a fatal error, 0 otherwise.
14431443
*/
14441444
static int
14451445
nc_server_ssh_auth(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message msg,
1446-
int method, const char *str_method, int local_users_supported, struct nc_auth_state *state)
1446+
int method, const char *str_method, int local_users_supported, struct nc_auth_state *auth_state)
14471447
{
14481448
const char *username;
1449-
int libssh_auth_methods = 0, ret = 0;
1449+
int ret = 0;
14501450
uint16_t i;
14511451
struct nc_auth_client *auth_client = NULL;
14521452
struct nc_endpt *referenced_endpt;
@@ -1473,7 +1473,7 @@ nc_server_ssh_auth(struct nc_session *session, struct nc_server_ssh_opts *opts,
14731473
}
14741474

14751475
return nc_server_ssh_auth(session, referenced_endpt->opts.ssh, msg, method,
1476-
str_method, local_users_supported, state);
1476+
str_method, local_users_supported, auth_state);
14771477
}
14781478

14791479
/* user not known, set his authentication methods to public key only so that
@@ -1495,29 +1495,29 @@ nc_server_ssh_auth(struct nc_session *session, struct nc_server_ssh_opts *opts,
14951495
(auth_client->store == NC_STORE_TRUSTSTORE) || (auth_client->store == NC_STORE_SYSTEM)) {
14961496
/* either locally configured pubkeys, or truststore or system (need to check for
14971497
* pubkey count, because NC_STORE_LOCAL is the default enum value) */
1498-
state->auth_method_count++;
1499-
libssh_auth_methods |= SSH_AUTH_METHOD_PUBLICKEY;
1498+
auth_state->methods |= SSH_AUTH_METHOD_PUBLICKEY;
1499+
auth_state->method_count++;
15001500
}
15011501
if (auth_client->password) {
1502-
state->auth_method_count++;
1503-
libssh_auth_methods |= SSH_AUTH_METHOD_PASSWORD;
1502+
auth_state->methods |= SSH_AUTH_METHOD_PASSWORD;
1503+
auth_state->method_count++;
15041504
}
15051505
if (auth_client->kb_int_enabled) {
1506-
state->auth_method_count++;
1507-
libssh_auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
1506+
auth_state->methods |= SSH_AUTH_METHOD_INTERACTIVE;
1507+
auth_state->method_count++;
15081508
}
15091509
if (auth_client->none_enabled) {
1510-
state->auth_method_count++;
1511-
libssh_auth_methods |= SSH_AUTH_METHOD_NONE;
1510+
auth_state->methods |= SSH_AUTH_METHOD_NONE;
1511+
auth_state->method_count++;
15121512
}
15131513
} else {
15141514
/* no local users meaning pw, pubkey and kbdint methods are supported, method count is set to 1,
1515-
* because only one method is needed for successul auth */
1516-
state->auth_method_count = 1;
1517-
libssh_auth_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE;
1515+
* because only one method is needed for successful auth */
1516+
auth_state->methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE;
1517+
auth_state->method_count = 1;
15181518
}
15191519

1520-
ssh_set_auth_methods(session->ti.libssh.session, libssh_auth_methods);
1520+
ssh_set_auth_methods(session->ti.libssh.session, auth_state->methods);
15211521
} else {
15221522
if (strcmp(username, session->username)) {
15231523
/* changing username not allowed */
@@ -1547,11 +1547,13 @@ nc_server_ssh_auth(struct nc_session *session, struct nc_server_ssh_opts *opts,
15471547
}
15481548

15491549
if (!ret) {
1550-
state->auth_success_count++;
1550+
auth_state->success_methods |= method;
1551+
auth_state->success_count++;
15511552

1552-
if (state->auth_success_count < state->auth_method_count) {
1553+
if (auth_state->success_count < auth_state->method_count) {
15531554
/* success, but he needs to do another method */
15541555
VRB(session, "User \"%s\" partially authenticated, but still needs to authenticate via the rest of his configured methods.", username);
1556+
ssh_set_auth_methods(session->ti.libssh.session, auth_state->methods & ~auth_state->success_methods);
15551557
ssh_message_auth_reply_success(msg, 1);
15561558
} else {
15571559
/* authenticated */
@@ -1571,7 +1573,7 @@ nc_server_ssh_auth(struct nc_session *session, struct nc_server_ssh_opts *opts,
15711573
}
15721574

15731575
int
1574-
nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message msg, struct nc_auth_state *state)
1576+
nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts, ssh_message msg, struct nc_auth_state *auth_state)
15751577
{
15761578
const char *str_type, *str_subtype = NULL;
15771579
int subtype, type, rc, local_users_supported;
@@ -1707,7 +1709,7 @@ nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts,
17071709
ERR(session, "User \"%s\" authenticated, but requested another authentication.", session->username);
17081710
ssh_message_reply_default(msg);
17091711
return 0;
1710-
} else if (!state || !opts) {
1712+
} else if (!auth_state || !opts) {
17111713
/* these two parameters should always be set during an authentication,
17121714
* however do a check just in case something goes really wrong, since they
17131715
* are not needed for other types of messages
@@ -1738,7 +1740,7 @@ nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts,
17381740
}
17391741

17401742
/* authenticate */
1741-
return nc_server_ssh_auth(session, opts, msg, subtype, str_subtype, local_users_supported, state);
1743+
return nc_server_ssh_auth(session, opts, msg, subtype, str_subtype, local_users_supported, auth_state);
17421744
} else if (session->flags & NC_SESSION_SSH_AUTHENTICATED) {
17431745
if ((type == SSH_REQUEST_CHANNEL_OPEN) && ((enum ssh_channel_type_e)subtype == SSH_CHANNEL_SESSION)) {
17441746
if (nc_server_ssh_channel_open(session, msg)) {
@@ -1862,7 +1864,7 @@ nc_accept_ssh_session_auth(struct nc_session *session, struct nc_server_ssh_opts
18621864
{
18631865
struct timespec ts_timeout;
18641866
ssh_message msg;
1865-
struct nc_auth_state state = {0};
1867+
struct nc_auth_state auth_state = {0};
18661868

18671869
/* authenticate */
18681870
if (opts->auth_timeout) {
@@ -1876,7 +1878,7 @@ nc_accept_ssh_session_auth(struct nc_session *session, struct nc_server_ssh_opts
18761878

18771879
msg = ssh_message_get(session->ti.libssh.session);
18781880
if (msg) {
1879-
if (nc_session_ssh_msg(session, opts, msg, &state)) {
1881+
if (nc_session_ssh_msg(session, opts, msg, &auth_state)) {
18801882
ssh_message_reply_default(msg);
18811883
}
18821884
ssh_message_free(msg);

0 commit comments

Comments
 (0)