1
0
mirror of https://github.com/libssh2/libssh2.git synced 2026-01-06 14:21:57 +03:00

ssh: Add support for userauth banner.

The new libssh2_userauth_banner API allows to get an optional
userauth banner sent with SSH_MSG_USERAUTH_BANNER packet by the
server.

Closes #610
This commit is contained in:
Sunil Nimmagadda
2021-06-02 21:02:55 +05:30
committed by Daniel Stenberg
parent 13ad7b2f5c
commit d5ed0e6536
7 changed files with 118 additions and 2 deletions

View File

@@ -194,6 +194,7 @@ set(MAN_PAGES
libssh2_trace.3
libssh2_trace_sethandler.3
libssh2_userauth_authenticated.3
libssh2_userauth_banner.3
libssh2_userauth_hostbased_fromfile.3
libssh2_userauth_hostbased_fromfile_ex.3
libssh2_userauth_keyboard_interactive.3

View File

@@ -164,6 +164,7 @@ dist_man_MANS = \
libssh2_trace.3 \
libssh2_trace_sethandler.3 \
libssh2_userauth_authenticated.3 \
libssh2_userauth_banner.3 \
libssh2_userauth_hostbased_fromfile.3 \
libssh2_userauth_hostbased_fromfile_ex.3 \
libssh2_userauth_keyboard_interactive.3 \

View File

@@ -0,0 +1,30 @@
.TH libssh2_userauth_banner 3 "1 Jun 2021" "libssh2 1.9.0" "libssh2 manual"
.SH NAME
libssh2_userauth_banner - get the server's userauth banner message
.SH SYNOPSIS
.nf
#include <libssh2.h>
int
libssh2_userauth_banner(LIBSSH2_SESSION *session, char **banner);
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init_ex(3)
\fIbanner\fP - Should point to a pointer that gets filled with banner message.
After an authentication has been attempted, such as a
\fBSSH_USERAUTH_NONE\fP request sent by
.BR libssh2_userauth_list(3) ,
this function can be called to retrieve the userauth banner sent by
the server. If no such banner is sent, or if an authentication has not
yet been attempted, returns LIBSSH2_ERROR_MISSING_USERAUTH_BANNER.
.SH RETURN VALUE
On success returns 0 and an UTF-8 NUL-terminated string is stored in the
\fIbanner\fP. This string is internally managed by libssh2 and will be
deallocated upon session termination.
On failure returns
LIBSSH2_ERROR_MISSING_USERAUTH_BANNER.
.SH SEE ALSO
.BR libssh2_session_init_ex(3),
.BR libssh2_userauth_list(3)

View File

@@ -507,6 +507,7 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL -47
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
#define LIBSSH2_ERROR_RANDGEN -49
#define LIBSSH2_ERROR_MISSING_USERAUTH_BANNER -50
/* this is a define to provide the old (<= 1.2.7) name */
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
@@ -615,6 +616,8 @@ LIBSSH2_API const char *libssh2_session_banner_get(LIBSSH2_SESSION *session);
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session,
const char *username,
unsigned int username_len);
LIBSSH2_API int libssh2_userauth_banner(LIBSSH2_SESSION *session,
char **banner);
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
LIBSSH2_API int

View File

@@ -720,6 +720,7 @@ struct _LIBSSH2_SESSION
libssh2_nonblocking_states userauth_list_state;
unsigned char *userauth_list_data;
size_t userauth_list_data_len;
char *userauth_banner;
packet_requirev_state_t userauth_list_packet_requirev_state;
/* State variables used in libssh2_userauth_password_ex() */

View File

@@ -994,6 +994,9 @@ session_free(LIBSSH2_SESSION *session)
if(session->userauth_list_data) {
LIBSSH2_FREE(session, session->userauth_list_data);
}
if(session->userauth_banner) {
LIBSSH2_FREE(session, session->userauth_banner);
}
if(session->userauth_pswd_data) {
LIBSSH2_FREE(session, session->userauth_pswd_data);
}

View File

@@ -63,11 +63,13 @@
static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
unsigned int username_len)
{
static const unsigned char reply_codes[3] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned char reply_codes[4] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
SSH_MSG_USERAUTH_BANNER, 0 };
/* packet_type(1) + username_len(4) + service_len(4) +
service(14)"ssh-connection" + method_len(4) = 27 */
unsigned long methods_len;
unsigned int banner_len;
unsigned char *s;
int rc;
@@ -134,6 +136,57 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
return NULL;
}
if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_BANNER) {
if(session->userauth_list_data_len < 5) {
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Unexpected packet size");
return NULL;
}
banner_len = _libssh2_ntohu32(session->userauth_list_data + 1);
if(banner_len >= session->userauth_list_data_len - 5) {
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
_libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Unexpected userauth banner size");
return NULL;
}
session->userauth_banner = LIBSSH2_ALLOC(session, banner_len);
if(!session->userauth_banner) {
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for userauth_banner");
return NULL;
}
memmove(session->userauth_banner, session->userauth_list_data + 5,
banner_len);
session->userauth_banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
"Banner: %s",
session->userauth_banner);
LIBSSH2_FREE(session, session->userauth_list_data);
session->userauth_list_data = NULL;
/* SSH_MSG_USERAUTH_BANNER has been handled */
reply_codes[2] = 0;
rc = _libssh2_packet_requirev(session, reply_codes,
&session->userauth_list_data,
&session->userauth_list_data_len, 0,
NULL, 0,
&session->userauth_list_packet_requirev_state);
if(rc == LIBSSH2_ERROR_EAGAIN) {
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block requesting userauth list");
return NULL;
}
else if(rc || (session->userauth_list_data_len < 1)) {
_libssh2_error(session, rc, "Failed getting response");
session->userauth_list_state = libssh2_NB_state_idle;
return NULL;
}
}
if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
/* Wow, who'dve thought... */
_libssh2_error(session, LIBSSH2_ERROR_NONE, "No error");
@@ -189,6 +242,30 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user,
return ptr;
}
/* libssh2_userauth_banner
*
* Retrieve banner message from server, if available.
* When no such message is sent by server or if no authentication attempt has
* been made, this function returns LIBSSH2_ERROR_MISSING_AUTH_BANNER.
*/
LIBSSH2_API int
libssh2_userauth_banner(LIBSSH2_SESSION *session, char **banner)
{
if(NULL == session)
return LIBSSH2_ERROR_MISSING_USERAUTH_BANNER;
if(!session->userauth_banner) {
return _libssh2_error(session,
LIBSSH2_ERROR_MISSING_USERAUTH_BANNER,
"Missing userauth banner");
}
if(banner != NULL)
*banner = session->userauth_banner;
return LIBSSH2_ERROR_NONE;
}
/*
* libssh2_userauth_authenticated
*