Skip to content

Commit 3bc2f58

Browse files
committed
Add optional authentication methods for ssh pubkey and interactive.
1 parent 6e4c4b5 commit 3bc2f58

3 files changed

Lines changed: 71 additions & 17 deletions

File tree

src/session_p.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ struct nc_server_opts {
169169
int (*passwd_auth_clb)(const struct nc_session *session, const char *password, void *user_data);
170170
void *passwd_auth_data;
171171
void (*passwd_auth_data_free)(void *data);
172+
173+
int (*pubkey_auth_clb)(const struct nc_session *session, ssh_key key, void *user_data);
174+
void *pubkey_auth_data;
175+
void (*pubkey_auth_data_free)(void *data);
176+
177+
int (*interactive_auth_clb)(const struct nc_session *session, const char* password,void *user_data);
178+
void *interactive_auth_data;
179+
void (*interactive_auth_data_free)(void *data);
172180
#endif
173181
#ifdef NC_ENABLED_TLS
174182
int (*user_verify_clb)(const struct nc_session *session);

src/session_server.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
# include <openssl/x509.h>
2323
#endif
2424

25+
#ifdef NC_ENABLED_SSH
26+
# include <libssh/libssh.h>
27+
# include <libssh/callbacks.h>
28+
# include <libssh/server.h>
29+
#endif
30+
2531
#include "session.h"
2632
#include "netconf.h"
2733

@@ -507,6 +513,29 @@ void nc_server_ssh_set_passwd_auth_clb(int (*passwd_auth_clb)(const struct nc_se
507513
void *user_data),
508514
void *user_data, void (*free_user_data)(void *user_data));
509515

516+
/**
517+
* @brief Set the callback for SSH interactive authentication. If none is set, local system users are used.
518+
*
519+
* @param[in] interactive_auth_clb Callback that should authenticate the user.
520+
* Zero return indicates success, non-zero an error.
521+
* @param[in] user_data Optional arbitrary user data that will be passed to \p passwd_auth_clb.
522+
* @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
523+
*/
524+
void ncserver_ssh_set_interactive_auth_clb(int (*interactive_auth_clb)(const struct nc_session *session, const char *password,
525+
void *user_data),
526+
void *user_data, void (*free_user_data)(void *user_data));
527+
528+
/**
529+
* @brief Set the callback for SSH public key authentication. If none is set, local system users are used.
530+
*
531+
* @param[in] pubkey_auth_clb Callback that should authenticate the user.
532+
* Zero return indicates success, non-zero an error.
533+
* @param[in] user_data Optional arbitrary user data that will be passed to \p passwd_auth_clb.
534+
* @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
535+
*/
536+
void ncserver_ssh_set_pubkey_auth_clb(int (*pubkey_auth_clb)(const struct nc_session *session, ssh_key key, void *user_data),
537+
void *user_data, void (*free_user_data)(void *user_data));
538+
510539
/**
511540
* @brief Set the callback for retrieving host keys. Any RSA, DSA, and ECDSA keys can be added. However,
512541
* a maximum of one key of each type will be used during SSH authentication, later keys replacing

src/session_server_ssh.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -820,33 +820,43 @@ nc_sshcb_auth_password(struct nc_session *session, ssh_message msg)
820820
static void
821821
nc_sshcb_auth_kbdint(struct nc_session *session, ssh_message msg)
822822
{
823+
int auth_ret = 1;
823824
char *pass_hash;
824-
825+
// Print message for interactive SSH
825826
if (!ssh_message_auth_kbdint_is_response(msg)) {
826827
const char *prompts[] = {"Password: "};
827828
char echo[] = {0};
828829

829830
ssh_message_auth_interactive_request(msg, "Interactive SSH Authentication", "Type your password:", 1, prompts, echo);
830831
} else {
831-
if (ssh_userauth_kbdint_getnanswers(session->ti.libssh.session) != 1) {
832+
if (ssh_userauth_kbdint_getnanswers(session->ti.libssh.session) != 1) {// failed session
832833
ssh_message_reply_default(msg);
833-
return;
834+
return auth_ret;
834835
}
835-
pass_hash = auth_password_get_pwd_hash(session->username);
836-
if (!pass_hash) {
837-
ssh_message_reply_default(msg);
838-
return;
836+
// Check the authentication type
837+
if (server_opts.interactive_auth_clb)
838+
{
839+
auth_ret = server_opts.interactive_auth_clb(session, ssh_message_auth_password(msg), server_opts.interactive_auth_clb);
839840
}
840-
if (!auth_password_compare_pwd(pass_hash, ssh_userauth_kbdint_getanswer(session->ti.libssh.session, 0))) {
841-
VRB("User \"%s\" authenticated.", session->username);
841+
else {
842+
pass_hash = auth_password_get_pwd_hash(session->username);// get hashed password
843+
if (pass_hash) {
844+
auth_ret = auth_password_compare_pwd(pass_hash, ssh_userauth_kbdint_getanswer(session->ti.libssh.session, 0));
845+
free(pass_hash);// free hashed password
846+
}
847+
}
848+
// Authenticate message based on outcome
849+
if (!auth_ret)
850+
{
842851
session->flags |= NC_SESSION_SSH_AUTHENTICATED;
852+
VRB("User \"%s\" authenticated.", session->username);
843853
ssh_message_auth_reply_success(msg, 0);
844-
} else {
854+
}
855+
else {
845856
++session->opts.server.ssh_auth_attempts;
846857
VRB("Failed user \"%s\" authentication attempt (#%d).", session->username, session->opts.server.ssh_auth_attempts);
847858
ssh_message_reply_default(msg);
848859
}
849-
free(pass_hash);
850860
}
851861
}
852862

@@ -909,12 +919,19 @@ nc_sshcb_auth_pubkey(struct nc_session *session, ssh_message msg)
909919
const char *username;
910920
int signature_state;
911921

912-
if ((username = auth_pubkey_compare_key(ssh_message_auth_pubkey(msg))) == NULL) {
913-
VRB("User \"%s\" tried to use an unknown (unauthorized) public key.", session->username);
914-
goto fail;
915-
} else if (strcmp(session->username, username)) {
916-
VRB("User \"%s\" is not the username identified with the presented public key.", session->username);
917-
goto fail;
922+
if(server_opts.pubkey_auth_clb){
923+
if(server_opts.pubkey_auth_clb(session, ssh_message_auth_pubkey(msg), server_opts.pubkey_auth_data)){
924+
goto fail;
925+
}
926+
}
927+
else{
928+
if ((username = auth_pubkey_compare_key(ssh_message_auth_pubkey(msg))) == NULL) {
929+
VRB("User \"%s\" tried to use an unknown (unauthorized) public key.", session->username);
930+
goto fail;
931+
} else if (strcmp(session->username, username)) {
932+
VRB("User \"%s\" is not the username identified with the presented public key.", session->username);
933+
goto fail;
934+
}
918935
}
919936

920937
signature_state = ssh_message_auth_publickey_state(msg);

0 commit comments

Comments
 (0)