diff --git a/examples/samplesshd-cb.c b/examples/samplesshd-cb.c index 628013aa..e5b48994 100644 --- a/examples/samplesshd-cb.c +++ b/examples/samplesshd-cb.c @@ -49,6 +49,27 @@ static int tries = 0; static int error = 0; static ssh_channel chan=NULL; +static int auth_none(ssh_session session, + const char *user, + void *userdata) +{ + ssh_string banner = NULL; + + (void)user; /* unused */ + (void)userdata; /* unused */ + + ssh_set_auth_methods(session, + SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); + + banner = ssh_string_from_char("Banner Example\n"); + if (banner != NULL) { + ssh_send_issue_banner(session, banner); + } + ssh_string_free(banner); + + return SSH_AUTH_DENIED; +} + static int auth_password(ssh_session session, const char *user, const char *password, void *userdata){ (void)userdata; @@ -242,6 +263,7 @@ int main(int argc, char **argv){ ssh_event mainloop; struct ssh_server_callbacks_struct cb = { .userdata = NULL, + .auth_none_function = auth_none, .auth_password_function = auth_password, #ifdef WITH_GSSAPI .auth_gssapi_mic_function = auth_gssapi_mic, diff --git a/include/libssh/server.h b/include/libssh/server.h index 27ee5790..c1a9c15c 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -245,6 +245,18 @@ LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o); */ LIBSSH_API void ssh_set_auth_methods(ssh_session session, int auth_methods); +/** + * @brief Send the server's issue-banner to client. + * + * + * @param[in] session The server session. + * + * @param[in] banner The server's banner. + * + * @return SSH_OK on success, SSH_ERROR on error. + */ +LIBSSH_API int ssh_send_issue_banner(ssh_session session, const ssh_string banner); + /********************************************************** * SERVER MESSAGING **********************************************************/ diff --git a/src/server.c b/src/server.c index fd078fde..e33c9366 100644 --- a/src/server.c +++ b/src/server.c @@ -524,6 +524,30 @@ void ssh_set_auth_methods(ssh_session session, int auth_methods) session->auth.supported_methods = (uint32_t)auth_methods & 0x3fU; } +int ssh_send_issue_banner(ssh_session session, const ssh_string banner) +{ + int rc = SSH_ERROR; + + if (session == NULL) { + return SSH_ERROR; + } + + SSH_LOG(SSH_LOG_PACKET, + "Sending a server issue banner"); + + rc = ssh_buffer_pack(session->out_buffer, + "bS", + SSH2_MSG_USERAUTH_BANNER, + banner); + if (rc != SSH_OK) { + ssh_set_error_oom(session); + return SSH_ERROR; + } + + rc = ssh_packet_send(session); + return rc; +} + /* Do the banner and key exchange */ int ssh_handle_key_exchange(ssh_session session) { int rc; diff --git a/tests/server/test_server/default_cb.c b/tests/server/test_server/default_cb.c index 03c34190..a0a874f4 100644 --- a/tests/server/test_server/default_cb.c +++ b/tests/server/test_server/default_cb.c @@ -51,6 +51,40 @@ #include #endif +int auth_none_cb(UNUSED_PARAM(ssh_session session), + const char *user, + void *userdata) +{ + struct session_data_st *sdata = NULL; + ssh_string banner = NULL; + + sdata = (struct session_data_st *)userdata; + if (sdata == NULL) { + fprintf(stderr, "Error: NULL userdata\n"); + goto denied; + } + + if (sdata->username == NULL) { + fprintf(stderr, "Error: expected username not set\n"); + goto denied; + } + + printf("None authentication of user %s\n", user); + + /* Send the banner */ + banner = ssh_string_from_char(SSHD_BANNER_MESSAGE); + if (banner == NULL) { + goto denied; + } + if (ssh_send_issue_banner(session, banner) == SSH_ERROR) { + fprintf(stderr, "Error: Failed to send the banner.\n"); + goto denied; + } +denied: + ssh_string_free(banner); + return SSH_AUTH_DENIED; +} + int auth_pubkey_cb(UNUSED_PARAM(ssh_session session), const char *user, UNUSED_PARAM(struct ssh_key_struct *pubkey), @@ -743,6 +777,7 @@ struct ssh_server_callbacks_struct *get_default_server_cb(void) goto end; } + cb->auth_none_function = auth_none_cb; cb->auth_password_function = auth_password_cb; cb->auth_pubkey_function = auth_pubkey_cb; cb->channel_open_request_session_function = channel_new_session_cb; diff --git a/tests/server/test_server/default_cb.h b/tests/server/test_server/default_cb.h index 487794c0..ecfd6515 100644 --- a/tests/server/test_server/default_cb.h +++ b/tests/server/test_server/default_cb.h @@ -32,6 +32,8 @@ #define SSHD_DEFAULT_ADDRESS "127.0.0.1" #define SSHD_DEFAULT_PCAP_FILE "debug.server.pcap" +#define SSHD_BANNER_MESSAGE "Test Banner Message\nlibssh-send-banner\n" + #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER diff --git a/tests/server/torture_server.c b/tests/server/torture_server.c index 910cd1bd..fecf86c9 100644 --- a/tests/server/torture_server.c +++ b/tests/server/torture_server.c @@ -174,6 +174,7 @@ static void torture_server_auth_none(void **state) struct test_server_st *tss = *state; struct torture_state *s = NULL; ssh_session session = NULL; + char *banner = NULL; int rc; assert_non_null(tss); @@ -193,6 +194,11 @@ static void torture_server_auth_none(void **state) rc = ssh_userauth_none(session, NULL); assert_int_equal(rc, SSH_AUTH_DENIED); + banner = ssh_get_issue_banner(session); + assert_string_equal(banner, SSHD_BANNER_MESSAGE); + free(banner); + banner = NULL; + /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);