Skip to content

Commit 1d52512

Browse files
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 issue 610
1 parent 06b90ef commit 1d52512

7 files changed

Lines changed: 118 additions & 2 deletions

File tree

vendor/libssh2/docs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ set(MAN_PAGES
193193
libssh2_trace.3
194194
libssh2_trace_sethandler.3
195195
libssh2_userauth_authenticated.3
196+
libssh2_userauth_banner.3
196197
libssh2_userauth_hostbased_fromfile.3
197198
libssh2_userauth_hostbased_fromfile_ex.3
198199
libssh2_userauth_keyboard_interactive.3

vendor/libssh2/docs/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ dist_man_MANS = \
163163
libssh2_trace.3 \
164164
libssh2_trace_sethandler.3 \
165165
libssh2_userauth_authenticated.3 \
166+
libssh2_userauth_banner.3 \
166167
libssh2_userauth_hostbased_fromfile.3 \
167168
libssh2_userauth_hostbased_fromfile_ex.3 \
168169
libssh2_userauth_keyboard_interactive.3 \
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.TH libssh2_userauth_banner 3 "1 Jun 2021" "libssh2 1.9.0" "libssh2 manual"
2+
.SH NAME
3+
libssh2_userauth_banner - get the server's userauth banner message
4+
.SH SYNOPSIS
5+
.nf
6+
#include <libssh2.h>
7+
8+
int
9+
libssh2_userauth_banner(LIBSSH2_SESSION *session, char **banner);
10+
.SH DESCRIPTION
11+
\fIsession\fP - Session instance as returned by
12+
.BR libssh2_session_init_ex(3)
13+
14+
\fIbanner\fP - Should point to a pointer that gets filled with banner message.
15+
16+
After an authentication has been attempted, such as a
17+
\fBSSH_USERAUTH_NONE\fP request sent by
18+
.BR libssh2_userauth_list(3) ,
19+
this function can be called to retrieve the userauth banner sent by
20+
the server. If no such banner is sent, or if an authentication has not
21+
yet been attempted, returns LIBSSH2_ERROR_MISSING_USERAUTH_BANNER.
22+
.SH RETURN VALUE
23+
On success returns 0 and an UTF-8 NUL-terminated string is stored in the
24+
\fIbanner\fP. This string is internally managed by libssh2 and will be
25+
deallocated upon session termination.
26+
On failure returns
27+
LIBSSH2_ERROR_MISSING_USERAUTH_BANNER.
28+
.SH SEE ALSO
29+
.BR libssh2_session_init_ex(3),
30+
.BR libssh2_userauth_list(3)

vendor/libssh2/include/libssh2.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ typedef struct _LIBSSH2_POLLFD {
507507
#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL -47
508508
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
509509
#define LIBSSH2_ERROR_RANDGEN -49
510+
#define LIBSSH2_ERROR_MISSING_USERAUTH_BANNER -50
510511

511512
/* this is a define to provide the old (<= 1.2.7) name */
512513
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
@@ -615,6 +616,8 @@ LIBSSH2_API const char *libssh2_session_banner_get(LIBSSH2_SESSION *session);
615616
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session,
616617
const char *username,
617618
unsigned int username_len);
619+
LIBSSH2_API int libssh2_userauth_banner(LIBSSH2_SESSION *session,
620+
char **banner);
618621
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
619622

620623
LIBSSH2_API int

vendor/libssh2/src/libssh2_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ struct _LIBSSH2_SESSION
720720
libssh2_nonblocking_states userauth_list_state;
721721
unsigned char *userauth_list_data;
722722
size_t userauth_list_data_len;
723+
char *userauth_banner;
723724
packet_requirev_state_t userauth_list_packet_requirev_state;
724725

725726
/* State variables used in libssh2_userauth_password_ex() */

vendor/libssh2/src/session.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,9 @@ session_free(LIBSSH2_SESSION *session)
994994
if(session->userauth_list_data) {
995995
LIBSSH2_FREE(session, session->userauth_list_data);
996996
}
997+
if(session->userauth_banner) {
998+
LIBSSH2_FREE(session, session->userauth_banner);
999+
}
9971000
if(session->userauth_pswd_data) {
9981001
LIBSSH2_FREE(session, session->userauth_pswd_data);
9991002
}

vendor/libssh2/src/userauth.c

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,13 @@
6363
static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
6464
unsigned int username_len)
6565
{
66-
static const unsigned char reply_codes[3] =
67-
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
66+
unsigned char reply_codes[4] =
67+
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
68+
SSH_MSG_USERAUTH_BANNER, 0 };
6869
/* packet_type(1) + username_len(4) + service_len(4) +
6970
service(14)"ssh-connection" + method_len(4) = 27 */
7071
unsigned long methods_len;
72+
unsigned int banner_len;
7173
unsigned char *s;
7274
int rc;
7375

@@ -134,6 +136,57 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
134136
return NULL;
135137
}
136138

139+
if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_BANNER) {
140+
if(session->userauth_list_data_len < 5) {
141+
LIBSSH2_FREE(session, session->userauth_list_data);
142+
session->userauth_list_data = NULL;
143+
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
144+
"Unexpected packet size");
145+
return NULL;
146+
}
147+
banner_len = _libssh2_ntohu32(session->userauth_list_data + 1);
148+
if(banner_len >= session->userauth_list_data_len - 5) {
149+
LIBSSH2_FREE(session, session->userauth_list_data);
150+
session->userauth_list_data = NULL;
151+
_libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
152+
"Unexpected userauth banner size");
153+
return NULL;
154+
}
155+
session->userauth_banner = LIBSSH2_ALLOC(session, banner_len);
156+
if(!session->userauth_banner) {
157+
LIBSSH2_FREE(session, session->userauth_list_data);
158+
session->userauth_list_data = NULL;
159+
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
160+
"Unable to allocate memory for userauth_banner");
161+
return NULL;
162+
}
163+
memmove(session->userauth_banner, session->userauth_list_data + 5,
164+
banner_len);
165+
session->userauth_banner[banner_len] = '\0';
166+
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
167+
"Banner: %s",
168+
session->userauth_banner);
169+
LIBSSH2_FREE(session, session->userauth_list_data);
170+
session->userauth_list_data = NULL;
171+
/* SSH_MSG_USERAUTH_BANNER has been handled */
172+
reply_codes[2] = 0;
173+
rc = _libssh2_packet_requirev(session, reply_codes,
174+
&session->userauth_list_data,
175+
&session->userauth_list_data_len, 0,
176+
NULL, 0,
177+
&session->userauth_list_packet_requirev_state);
178+
if(rc == LIBSSH2_ERROR_EAGAIN) {
179+
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
180+
"Would block requesting userauth list");
181+
return NULL;
182+
}
183+
else if(rc || (session->userauth_list_data_len < 1)) {
184+
_libssh2_error(session, rc, "Failed getting response");
185+
session->userauth_list_state = libssh2_NB_state_idle;
186+
return NULL;
187+
}
188+
}
189+
137190
if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
138191
/* Wow, who'dve thought... */
139192
_libssh2_error(session, LIBSSH2_ERROR_NONE, "No error");
@@ -189,6 +242,30 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user,
189242
return ptr;
190243
}
191244

245+
/* libssh2_userauth_banner
246+
*
247+
* Retrieve banner message from server, if available.
248+
* When no such message is sent by server or if no authentication attempt has
249+
* been made, this function returns LIBSSH2_ERROR_MISSING_AUTH_BANNER.
250+
*/
251+
LIBSSH2_API int
252+
libssh2_userauth_banner(LIBSSH2_SESSION *session, char **banner)
253+
{
254+
if(NULL == session)
255+
return LIBSSH2_ERROR_MISSING_USERAUTH_BANNER;
256+
257+
if(!session->userauth_banner) {
258+
return _libssh2_error(session,
259+
LIBSSH2_ERROR_MISSING_USERAUTH_BANNER,
260+
"Missing userauth banner");
261+
}
262+
263+
if(banner != NULL)
264+
*banner = session->userauth_banner;
265+
266+
return LIBSSH2_ERROR_NONE;
267+
}
268+
192269
/*
193270
* libssh2_userauth_authenticated
194271
*

0 commit comments

Comments
 (0)