Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions [email protected][email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ module libnetconf2-netconf-server {
prefix tlss;
}

revision "2025-06-02" {
description "Removed presence from the <keyboard-interactive> container.";
}

revision "2025-01-23" {
description "Added a list of YANG modules skipped in the server <hello> message.";
}
Expand Down Expand Up @@ -312,7 +316,6 @@ module libnetconf2-netconf-server {
"Grouping for the SSH Keyboard interactive authentication method.";

container keyboard-interactive {
presence "Indicates that the given client supports the SSH Keyboard Interactive authentication method.";
description
"Keyboard interactive SSH authentication method.";

Expand All @@ -322,7 +325,6 @@ module libnetconf2-netconf-server {
the Secure Shell Protocol (SSH)";

choice method {
mandatory true;
description
"Method to perform the authentication with.";

Expand Down
33 changes: 31 additions & 2 deletions src/server_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2188,6 +2188,33 @@ nc_server_config_password(const struct lyd_node *node, enum nc_operation op)
return ret;
}

static int
nc_server_config_keyboard_interactive(const struct lyd_node *node, enum nc_operation op)
{
struct nc_auth_client *auth_client;
struct nc_ch_client *ch_client = NULL;

assert(!strcmp(LYD_NAME(node), "keyboard-interactive"));

if (op != NC_OP_DELETE) {
/* only do something on delete */
return 0;
}

if (is_ch(node) && nc_server_config_get_ch_client(node, &ch_client)) {
return 1;
}

if (nc_server_config_get_auth_client(node, ch_client, &auth_client)) {
return 1;
}

/* delete the keyboard-interactive authentication method */
auth_client->kbdint_method = NC_KBDINT_AUTH_METHOD_NONE;

return 0;
}

static int
nc_server_config_use_system_auth(const struct lyd_node *node, enum nc_operation op)
{
Expand All @@ -2207,9 +2234,9 @@ nc_server_config_use_system_auth(const struct lyd_node *node, enum nc_operation
}

if (op == NC_OP_CREATE) {
auth_client->kb_int_enabled = 1;
auth_client->kbdint_method = NC_KBDINT_AUTH_METHOD_SYSTEM;
} else {
auth_client->kb_int_enabled = 0;
auth_client->kbdint_method = NC_KBDINT_AUTH_METHOD_NONE;
}

cleanup:
Expand Down Expand Up @@ -3598,6 +3625,8 @@ nc_server_config_parse_netconf_server(const struct lyd_node *node, enum nc_opera
ret = nc_server_config_idle_time(node, op);
} else if (!strcmp(name, "keepalives")) {
ret = nc_server_config_keepalives(node, op);
} else if (!strcmp(name, "keyboard-interactive")) {
ret = nc_server_config_keyboard_interactive(node, op);
} else if (!strcmp(name, "key-exchange-alg")) {
ret = nc_server_config_kex_alg(node, op);
} else if (!strcmp(name, "local-address")) {
Expand Down
25 changes: 17 additions & 8 deletions src/session_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ enum nc_privkey_format {
NC_PRIVKEY_FORMAT_UNKNOWN /**< Unknown format */
};

/**
* @brief Enumeration of SSH keyboard-interactive authentication methods.
*/
enum nc_kbdint_auth_method {
NC_KBDINT_AUTH_METHOD_NONE = 0, /**< Keyboard-interactive authentication disabled. */
NC_KBDINT_AUTH_METHOD_SYSTEM /**< Keyboard-interactive authentication is left to the system (PAM, shadow, etc.). */
};

/**
* @brief A basic certificate.
*/
Expand Down Expand Up @@ -175,20 +183,21 @@ struct nc_auth_state {
* @brief A server's authorized client.
*/
struct nc_auth_client {
char *username; /**< Arbitrary username. */
char *username; /**< Arbitrary username. */

enum nc_store_type store; /**< Specifies how/where the client's public key is stored. */
enum nc_store_type store; /**< Specifies how/where the client's public key is stored. */
union {
struct {
struct nc_public_key *pubkeys; /**< The client's public keys. */
uint16_t pubkey_count; /**< The number of client's public keys. */
struct nc_public_key *pubkeys; /**< The client's public keys. */
uint16_t pubkey_count; /**< The number of client's public keys. */
};
char *ts_ref; /**< Name of the referenced truststore key. */
char *ts_ref; /**< Name of the referenced truststore key. */
};

char *password; /**< Client's password */
int kb_int_enabled; /**< Indicates that the client supports keyboard-interactive authentication. */
int none_enabled; /**< Implies that the client supports the none authentication method. */
char *password; /**< Client's password */
enum nc_kbdint_auth_method kbdint_method; /**< Keyboard-interactive authentication method,
* may be extended by e.g. a union for each method when needed. */
int none_enabled; /**< Implies that the client supports the none authentication method. */
};

/**
Expand Down
49 changes: 36 additions & 13 deletions src/session_server_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ nc_server_ssh_auth_kbdint_pam(struct nc_session *session, const char *username,
* @return 0 on success, non-zero otherwise.
*/
static int
nc_server_ssh_auth_kbdint_system(struct nc_session *session, const char *username, ssh_message msg)
nc_server_ssh_auth_kbdint_passwd(struct nc_session *session, const char *username, ssh_message msg)
{
int ret = 0, n_answers;
const char *name = "Keyboard-Interactive Authentication";
Expand Down Expand Up @@ -975,6 +975,32 @@ nc_server_ssh_auth_kbdint_system(struct nc_session *session, const char *usernam

#endif

/**
* @brief Keyboard-interactive authentication method using the system's authentication methods.
*
* @param[in] session NETCONF session.
* @param[in] msg SSH message with a keyboard-interactive authentication request.
* @return 0 on success, non-zero otherwise.
*/
static int
nc_server_ssh_auth_kbdint_system(struct nc_session *session, ssh_message msg)
{
int rc;

#ifdef HAVE_LIBPAM
/* authenticate using PAM */
rc = nc_server_ssh_auth_kbdint_pam(session, session->username, msg);
#elif defined (HAVE_SHADOW)
/* authenticate using /etc/passwd and /etc/shadow */
rc = nc_server_ssh_auth_kbdint_passwd(session, session->username, msg);
#else
ERR(NULL, "Keyboard-interactive method not supported.");
rc = 1;
#endif

return rc;
}

API void
nc_server_ssh_set_interactive_auth_clb(int (*interactive_auth_clb)(const struct nc_session *session, ssh_session ssh_sess, ssh_message msg, void *user_data),
void *user_data, void (*free_user_data)(void *user_data))
Expand Down Expand Up @@ -1319,22 +1345,19 @@ nc_server_ssh_auth_kbdint(struct nc_session *session, int local_users_supported,

assert(!local_users_supported || auth_client);

if (local_users_supported && !auth_client->kb_int_enabled) {
if (local_users_supported && !auth_client->kbdint_method) {
VRB(session, "User \"%s\" does not have Keyboard-interactive method configured, but a request was received.", session->username);
return 1;
} else if (server_opts.interactive_auth_clb) {
rc = server_opts.interactive_auth_clb(session, session->ti.libssh.session, msg, server_opts.interactive_auth_data);
} else {
#ifdef HAVE_LIBPAM
/* authenticate using PAM */
rc = nc_server_ssh_auth_kbdint_pam(session, session->username, msg);
#elif defined (HAVE_SHADOW)
/* authenticate using the system */
rc = nc_server_ssh_auth_kbdint_system(session, session->username, msg);
#else
ERR(NULL, "Keyboard-interactive method not supported.");
return 1;
#endif
/* perform the authentication based on the configured method */
if (auth_client->kbdint_method == NC_KBDINT_AUTH_METHOD_SYSTEM) {
rc = nc_server_ssh_auth_kbdint_system(session, msg);
} else {
ERR(session, "Keyboard-interactive authentication method not supported.");
rc = 1;
}
}

return rc ? 1 : 0;
Expand Down Expand Up @@ -1509,7 +1532,7 @@ nc_server_ssh_auth(struct nc_session *session, struct nc_server_ssh_opts *opts,
auth_state->methods |= SSH_AUTH_METHOD_PASSWORD;
auth_state->method_count++;
}
if (auth_client->kb_int_enabled) {
if (auth_client->kbdint_method) {
auth_state->methods |= SSH_AUTH_METHOD_INTERACTIVE;
auth_state->method_count++;
}
Expand Down
12 changes: 2 additions & 10 deletions tests/library_valgrind.supp
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,11 @@
fun:ly_ctx_new
}
{
CI:test_pam:__wrap_pam_start
test_pam:__wrap_pam_start_leak
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
...
fun:ln2_glob_test_server_thread
fun:ln2_glob_test_server_thread
}
{
test_pam:__wrap_pam_start
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:__wrap_pam_start
...
fun:ln2_glob_test_server_thread
}