Skip to content

Commit e5675b1

Browse files
author
roman
committed
session server ssh UPDATE add kbdint helper API
Made a static function public. This new API helps get client's answers to kbdint prompts. Also added a more detailed documentation to kbdint callback setter. Helps resolve #462.
1 parent d82caf1 commit e5675b1

4 files changed

Lines changed: 56 additions & 26 deletions

File tree

src/io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ nc_read_msg_poll_io(struct nc_session *session, int io_timeout, struct ly_in **m
582582

583583
/* does not really log, only fatal errors */
584584
int
585-
nc_session_is_connected(struct nc_session *session)
585+
nc_session_is_connected(const struct nc_session *session)
586586
{
587587
int ret;
588588
struct pollfd fds;

src/session_p.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,6 @@ struct nc_ntf_thread_arg {
735735
struct nc_pam_thread_arg {
736736
ssh_message msg; /**< libssh message */
737737
struct nc_session *session; /**< NETCONF session */
738-
uint16_t auth_timeout; /**< Authentication timeout. */
739738
};
740739

741740
/**
@@ -1116,6 +1115,6 @@ NC_MSG_TYPE nc_write_msg_io(struct nc_session *session, int io_timeout, int type
11161115
* @param[in] session Session to check.
11171116
* @return 1 if connected, 0 if not.
11181117
*/
1119-
int nc_session_is_connected(struct nc_session *session);
1118+
int nc_session_is_connected(const struct nc_session *session);
11201119

11211120
#endif /* NC_SESSION_PRIVATE_H_ */

src/session_server.h

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,46 @@ NC_MSG_TYPE nc_ps_accept_ssh_channel(struct nc_pollsession *ps, struct nc_sessio
483483
int nc_server_ssh_set_authkey_path_format(const char *path);
484484

485485
/**
486-
* @brief Set the callback for SSH interactive authentication. If not set, local PAM-based authentication is used.
486+
* @brief Keyboard interactive authentication callback.
487487
*
488-
* @param[in] interactive_auth_clb Callback that should authenticate the user.
489-
* Zero return indicates success, non-zero an error.
488+
* The callback has to handle sending interactive challenges and receiving responses by itself.
489+
* An example callback may fit the following description:
490+
* Prepare all prompts for the user and send them via `ssh_message_auth_interactive_request()`.
491+
* Get the answers either by calling `ssh_message_get()` or `nc_server_ssh_kbdint_get_nanswers()`.
492+
* Return value based on your authentication logic and user answers retrieved by
493+
* calling `ssh_userauth_kbdint_getanswer()`.
494+
*
495+
* @param[in] session NETCONF session.
496+
* @param[in] ssh_sess libssh session.
497+
* @param[in] msg SSH message that contains the interactive request and which expects a reply with prompts.
498+
* @param[in] user_data Arbitrary user data.
499+
* @return 0 for successful authentication, non-zero to deny the user.
500+
*/
501+
typedef int (*nc_server_ssh_interactive_auth_clb)(const struct nc_session *session,
502+
ssh_session ssh_sess, ssh_message msg, void *user_data);
503+
504+
/**
505+
* @brief Set the callback for SSH interactive authentication.
506+
*
507+
* @param[in] auth_clb Keyboard interactive authentication callback. This callback is only called once per authentication.
490508
* @param[in] user_data Optional arbitrary user data that will be passed to @p interactive_auth_clb.
491509
* @param[in] free_user_data Optional callback that will be called during cleanup to free any @p user_data.
492510
*/
493-
void nc_server_ssh_set_interactive_auth_clb(int (*interactive_auth_clb)(const struct nc_session *session,
494-
ssh_session ssh_sess, ssh_message msg, void *user_data), void *user_data, void (*free_user_data)(void *user_data));
511+
void nc_server_ssh_set_interactive_auth_clb(nc_server_ssh_interactive_auth_clb auth_clb, void *user_data, void (*free_user_data)(void *user_data));
512+
513+
/**
514+
* @brief Get the number of answers to Keyboard interactive authentication prompts.
515+
*
516+
* The actual answers can later be retrieved by calling `ssh_userauth_kbdint_getanswer()` on
517+
* the @p libssh_session.
518+
*
519+
* @param[in] session NETCONF session.
520+
* @param[in] libssh_session libssh session.
521+
*
522+
* @return Non-negative number of answers on success, -1 on configurable authentication timeout,
523+
* disconnect or other error.
524+
*/
525+
int nc_server_ssh_kbdint_get_nanswers(const struct nc_session *session, ssh_session libssh_session);
495526

496527
/**
497528
* @brief Set the name of the PAM configuration file.

src/session_server_ssh.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -461,13 +461,15 @@ nc_sshcb_auth_password(struct nc_session *session, struct nc_auth_client *auth_c
461461
return auth_ret;
462462
}
463463

464-
/* get answers to kbdint prompts on the given libssh session and return the number of them, -1 on timeout/dc */
465-
static int
466-
nc_server_ssh_kbdint_get_nanswers(struct nc_session *session, ssh_session libssh_session, uint16_t auth_timeout)
464+
API int
465+
nc_server_ssh_kbdint_get_nanswers(const struct nc_session *session, ssh_session libssh_session)
467466
{
468467
int ret = 0;
469468
struct timespec ts_timeout = {0};
470469
ssh_message reply = NULL;
470+
uint16_t auth_timeout = *((uint16_t *)session->data);
471+
472+
NC_CHECK_ARG_RET(NULL, session, libssh_session, -1);
471473

472474
if (auth_timeout) {
473475
nc_timeouttime_get(&ts_timeout, auth_timeout * 1000);
@@ -523,10 +525,8 @@ nc_pam_conv_clb(int n_messages, const struct pam_message **msg, struct pam_respo
523525
ssh_message reply = NULL;
524526
struct nc_pam_thread_arg *clb_data = appdata_ptr;
525527
ssh_session libssh_session;
526-
uint16_t auth_timeout;
527528

528529
libssh_session = clb_data->session->ti.libssh.session;
529-
auth_timeout = clb_data->auth_timeout;
530530

531531
/* PAM_MAX_NUM_MSG == 32 by default */
532532
if ((n_messages <= 0) || (n_messages >= PAM_MAX_NUM_MSG)) {
@@ -598,7 +598,7 @@ nc_pam_conv_clb(int n_messages, const struct pam_message **msg, struct pam_respo
598598
goto cleanup;
599599
}
600600

601-
n_answers = nc_server_ssh_kbdint_get_nanswers(clb_data->session, libssh_session, auth_timeout);
601+
n_answers = nc_server_ssh_kbdint_get_nanswers(clb_data->session, libssh_session);
602602
if (n_answers < 0) {
603603
/* timeout or dc */
604604
r = PAM_CONV_ERR;
@@ -642,7 +642,7 @@ nc_pam_conv_clb(int n_messages, const struct pam_message **msg, struct pam_respo
642642
* @return PAM error otherwise.
643643
*/
644644
static int
645-
nc_pam_auth(struct nc_session *session, struct nc_auth_client *client, uint16_t auth_timeout, ssh_message ssh_msg)
645+
nc_pam_auth(struct nc_session *session, struct nc_auth_client *client, ssh_message ssh_msg)
646646
{
647647
pam_handle_t *pam_h = NULL;
648648
int ret;
@@ -652,7 +652,6 @@ nc_pam_auth(struct nc_session *session, struct nc_auth_client *client, uint16_t
652652
/* structure holding callback's data */
653653
clb_data.msg = ssh_msg;
654654
clb_data.session = session;
655-
clb_data.auth_timeout = auth_timeout;
656655

657656
/* PAM conversation structure holding the callback and it's data */
658657
conv.conv = nc_pam_conv_clb;
@@ -835,13 +834,12 @@ nc_server_ssh_get_pwd_hash(const char *username)
835834
*
836835
* @param[in] session Session to authenticate on.
837836
* @param[in] client Client to authenticate.
838-
* @param[in] auth_timeout Authentication timeout.
839837
* @param[in] msg SSH message that originally requested kbdint authentication.
840838
*
841839
* @return 0 on success, non-zero otherwise.
842840
*/
843841
static int
844-
nc_server_ssh_system_auth(struct nc_session *session, struct nc_auth_client *client, uint16_t auth_timeout, ssh_message msg)
842+
nc_server_ssh_system_auth(struct nc_session *session, struct nc_auth_client *client, ssh_message msg)
845843
{
846844
int ret = 0, n_answers;
847845
const char *name = "Keyboard-Interactive Authentication";
@@ -868,7 +866,7 @@ nc_server_ssh_system_auth(struct nc_session *session, struct nc_auth_client *cli
868866
}
869867

870868
/* get the reply */
871-
n_answers = nc_server_ssh_kbdint_get_nanswers(session, session->ti.libssh.session, auth_timeout);
869+
n_answers = nc_server_ssh_kbdint_get_nanswers(session, session->ti.libssh.session);
872870
if (n_answers < 0) {
873871
/* timeout or dc */
874872
ret = 1;
@@ -895,7 +893,7 @@ nc_server_ssh_system_auth(struct nc_session *session, struct nc_auth_client *cli
895893
#endif
896894

897895
static int
898-
nc_sshcb_auth_kbdint(struct nc_session *session, struct nc_auth_client *client, uint16_t auth_timeout, ssh_message msg)
896+
nc_sshcb_auth_kbdint(struct nc_session *session, struct nc_auth_client *client, ssh_message msg)
899897
{
900898
int auth_ret = 1;
901899

@@ -904,16 +902,15 @@ nc_sshcb_auth_kbdint(struct nc_session *session, struct nc_auth_client *client,
904902
} else {
905903
#ifdef HAVE_LIBPAM
906904
/* authenticate using PAM */
907-
if (!nc_pam_auth(session, client, auth_timeout, msg)) {
905+
if (!nc_pam_auth(session, client, msg)) {
908906
auth_ret = 0;
909907
}
910908
#elif defined (HAVE_SHADOW)
911909
/* authenticate using locally configured users */
912-
if (!nc_server_ssh_system_auth(session, client, auth_timeout, msg)) {
910+
if (!nc_server_ssh_system_auth(session, client, msg)) {
913911
auth_ret = 0;
914912
}
915913
#else
916-
(void) auth_timeout;
917914
ERR(NULL, "Keyboard-interactive method not supported.");
918915
#endif
919916
}
@@ -1506,7 +1503,7 @@ nc_session_ssh_msg(struct nc_session *session, struct nc_server_ssh_opts *opts,
15061503
} else if (subtype == SSH_AUTH_METHOD_PUBLICKEY) {
15071504
ret = nc_sshcb_auth_pubkey(session, auth_client, msg);
15081505
} else if (subtype == SSH_AUTH_METHOD_INTERACTIVE) {
1509-
ret = nc_sshcb_auth_kbdint(session, auth_client, opts->auth_timeout, msg);
1506+
ret = nc_sshcb_auth_kbdint(session, auth_client, msg);
15101507
}
15111508

15121509
if (!ret) {
@@ -1780,8 +1777,11 @@ nc_accept_ssh_session(struct nc_session *session, struct nc_server_ssh_opts *opt
17801777
goto cleanup;
17811778
}
17821779

1783-
/* authenticate */
1784-
if ((rc = nc_accept_ssh_session_auth(session, opts)) != 1) {
1780+
/* authenticate, store auth_timeout in session so we can retrieve it in kb interactive API */
1781+
session->data = &opts->auth_timeout;
1782+
rc = nc_accept_ssh_session_auth(session, opts);
1783+
session->data = NULL;
1784+
if (rc != 1) {
17851785
goto cleanup;
17861786
}
17871787

0 commit comments

Comments
 (0)