From 9c91ea1caf8a7263d830de0bbd5f3b183940b595 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Mon, 2 Aug 2004 04:25:05 +0000
Subject: [PATCH] Banner printing

--HG--
extra : convert_revision : a38558944355bb9b4c8e9e22147c1f2d8d327775
---
 auth.h        |  1 +
 cli-auth.c    | 42 ++++++++++++++++++++++++++++++++++++++++++
 cli-session.c | 22 ++++++++++++++++++++++
 options.h     |  1 +
 session.h     |  1 +
 5 files changed, 67 insertions(+)

diff --git a/auth.h b/auth.h
index df8ae0ce..106a1ad0 100644
--- a/auth.h
+++ b/auth.h
@@ -47,6 +47,7 @@ void recv_msg_userauth_success();
 void cli_get_user();
 void cli_auth_getmethods();
 void cli_auth_try();
+void recv_msg_userauth_banner();
 
 
 #define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
diff --git a/cli-auth.c b/cli-auth.c
index e0815872..549349e7 100644
--- a/cli-auth.c
+++ b/cli-auth.c
@@ -35,6 +35,48 @@ void cli_auth_getmethods() {
 
 }
 
+void recv_msg_userauth_banner() {
+
+	unsigned char* banner = NULL;
+	unsigned int bannerlen;
+	unsigned int i, linecount;
+
+	TRACE(("enter recv_msg_userauth_banner"));
+	if (ses.authstate.authdone) {
+		TRACE(("leave recv_msg_userauth_banner: banner after auth done"));
+		return;
+	}
+
+	banner = buf_getstring(ses.payload, &bannerlen);
+	buf_eatstring(ses.payload); /* The language string */
+
+	if (bannerlen > MAX_BANNER_SIZE) {
+		TRACE(("recv_msg_userauth_banner: bannerlen too long: %d", bannerlen));
+		goto out;
+	}
+
+	cleantext(banner);
+
+	/* Limit to 25 lines */
+	linecount = 1;
+	for (i = 0; i < bannerlen; i++) {
+		if (banner[i] == '\n') {
+			if (linecount >= MAX_BANNER_LINES) {
+				banner[i] = '\0';
+				break;
+			}
+			linecount++;
+		}
+	}
+
+	printf("%s\n", banner);
+
+out:
+	m_free(banner);
+	TRACE(("leave recv_msg_userauth_banner"));
+}
+
+
 void recv_msg_userauth_failure() {
 
 	unsigned char * methods = NULL;
diff --git a/cli-session.c b/cli-session.c
index 6882d2e3..e8c6ae6c 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -36,6 +36,7 @@ static const packettype cli_packettypes[] = {
 	{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
 	{SSH_MSG_USERAUTH_FAILURE, recv_msg_userauth_failure}, // client
 	{SSH_MSG_USERAUTH_SUCCESS, recv_msg_userauth_success}, // client
+	{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, // client
 	{0, 0} /* End */
 };
 
@@ -217,3 +218,24 @@ static void cli_remoteclosed() {
 	ses.sock = -1;
 	dropbear_exit("remote closed the connection");
 }
+
+/* Operates in-place turning dirty (untrusted potentially containing control
+ * characters) text into clean text. */
+void cleantext(unsigned char* dirtytext) {
+
+	unsigned int i, j;
+	unsigned char c, lastchar;
+
+	j = 0;
+	for (i = 0; dirtytext[i] != '\0'; i++) {
+
+		c = dirtytext[i];
+		/* We can ignore '\r's */
+		if ( (c >= ' ' && c <= '~') || c == '\n' || c == '\t') {
+			dirtytext[j] = c;
+			j++;
+		}
+	}
+	/* Null terminate */
+	dirtytext[j] = '\0';
+}
diff --git a/options.h b/options.h
index 1ab16c72..8ed21aba 100644
--- a/options.h
+++ b/options.h
@@ -195,6 +195,7 @@
 #endif
 
 #define MAX_BANNER_SIZE 2000 /* this is 25*80 chars, any more is foolish */
+#define MAX_BANNER_LINES 20 /* How many lines the client will display */
 
 #define DEV_URANDOM "/dev/urandom"
 
diff --git a/session.h b/session.h
index 20090544..23233770 100644
--- a/session.h
+++ b/session.h
@@ -56,6 +56,7 @@ void cli_session(int sock, char *remotehost);
 void cli_dropbear_exit(int exitcode, const char* format, va_list param);
 void cli_dropbear_log(int priority, const char* format, va_list param);
 void cli_session_cleanup();
+void cleantext(unsigned char* dirtytext);
 
 struct key_context {
 
-- 
GitLab