From d34c9a7ac63f221710f66ed43a6b24f7e074b4fb Mon Sep 17 00:00:00 2001
From: Florian Westphal <fw@strlen.de>
Date: Mon, 18 May 2009 00:29:02 +0200
Subject: [PATCH 2/4] SSL/TLS: Don't announce Zlib when SSL-layer compresses
 data

---
 src/ngircd/conn.c       |   42 +++++++++++++++++++++++++++++++++++++++++-
 src/ngircd/conn.h       |    2 ++
 src/ngircd/irc-server.c |   10 ++++++----
 src/ngircd/ngircd.c     |   23 ++---------------------
 4 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
index f832fae..5843920 100644
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -253,7 +253,7 @@ server_login(CONN_ID idx)
 	io_event_add( My_Connections[idx].sock, IO_WANTREAD|IO_WANTWRITE);
 
 	/* Send PASS and SERVER command to peer */
-	Conn_WriteStr( idx, "PASS %s %s", Conf_Server[Conf_GetServer( idx )].pwd_out, NGIRCd_ProtoID );
+	Conn_WriteStr( idx, "PASS %s %s", Conf_Server[Conf_GetServer( idx )].pwd_out, Conn_BuildProtoID(idx));
 	Conn_WriteStr( idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo );
 }
 
@@ -416,6 +416,46 @@ Conn_Init( void )
 } /* Conn_Init */
 
 
+/*
+ * Create protocol and server identification.
+ *
+ * The syntax used by ngIRCd in PASS commands and the extended flags
+ * are described in doc/Protocol.txt
+ *
+ * @param i connection index, may be< 0 to get compile-time constants.
+ * @return pointer to static buffer with the connection flags matching i.
+ */
+GLOBAL const char*
+Conn_BuildProtoID(CONN_ID i)
+{
+	static char proto[256];
+
+#ifdef IRCPLUS
+	snprintf(proto, sizeof(proto), "%s%s %s|%s:%s", PROTOVER, PROTOIRCPLUS,
+		 PACKAGE_NAME, PACKAGE_VERSION, IRCPLUSFLAGS);
+#ifdef ZLIB
+	/* don't bother with link compression if SSL already does it */
+	if (i < 0
+	    || !Conn_OPTION_ISSET(&My_Connections[i], CONN_SSL_COMPRESSION))
+		strlcat(proto, "Z", sizeof(proto));
+#endif
+	if (Conf_OperCanMode)
+		strlcat(proto, "o", sizeof(proto));
+#else /* IRCPLUS */
+	snprintf(proto, sizeof(proto), "%s%s %s|%s", PROTOVER, PROTOIRC,
+		 PACKAGE_NAME, PACKAGE_VERSION);
+#endif /* IRCPLUS */
+	strlcat(proto, " P", sizeof(proto));
+
+#ifdef ZLIB
+	if (i < 0 
+	    || !Conn_OPTION_ISSET(&My_Connections[i], CONN_SSL_COMPRESSION))
+		strlcat(proto, "Z", sizeof(proto));
+#endif
+	return proto;
+}
+
+
 /**
  * Clean up connection module.
  */
diff --git a/src/ngircd/conn.h b/src/ngircd/conn.h
index 97014c0..c7987ce 100644
--- a/src/ngircd/conn.h
+++ b/src/ngircd/conn.h
@@ -141,6 +141,8 @@ GLOBAL CONN_ID Conn_GetFromProc PARAMS((int fd));
 GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i));
 GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i));
 
+GLOBAL const char* Conn_BuildProtoID PARAMS((CONN_ID i));
+
 #ifdef SSL_SUPPORT
 GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
 GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
diff --git a/src/ngircd/irc-server.c b/src/ngircd/irc-server.c
index 61939fd..af0808b 100644
--- a/src/ngircd/irc-server.c
+++ b/src/ngircd/irc-server.c
@@ -133,8 +133,8 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
 		if (Client_Token(Client) != TOKEN_OUTBOUND) {
 			/* Incoming connection, send user/pass */
 			if (!IRC_WriteStrClient(Client, "PASS %s %s",
-						Conf_Server[i].pwd_out,
-						NGIRCd_ProtoID)
+					Conf_Server[i].pwd_out,
+					Conn_BuildProtoID(Client_Conn(Client)))
 			    || !IRC_WriteStrClient(Client, "SERVER %s 1 :%s",
 						   Conf_ServerName,
 						   Conf_ServerInfo)) {
@@ -163,9 +163,11 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
 		}
 
 		Client_SetType(Client, CLIENT_UNKNOWNSERVER);
-
 #ifdef ZLIB
-		if (strchr(Client_Flags(Client), 'Z')
+		/* Don't announce zlib support (server flag 'Z') to peer when
+		 * CONN_SSL_COMPRESSION is already set */
+		if (!(Conn_Options(Client_Conn(Client)) & CONN_SSL_COMPRESSION)
+		    && strchr(Client_Flags(Client), 'Z')
 		    && !Zip_InitConn(Client_Conn(Client))) {
 			Conn_Close(Client_Conn(Client),
 				   "Can't inizialize compression (zlib)!",
diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c
index f016b6a..8d45134 100644
--- a/src/ngircd/ngircd.c
+++ b/src/ngircd/ngircd.c
@@ -289,27 +289,8 @@ main(int argc, const char *argv[])
 			exit(1);
 		}
 
-		/* Create protocol and server identification. The syntax
-		 * used by ngIRCd in PASS commands and the known "extended
-		 * flags" are described in doc/Protocol.txt. */
-#ifdef IRCPLUS
-		snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s",
-			 PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
-			 IRCPLUSFLAGS);
-#ifdef ZLIB
-		strcat(NGIRCd_ProtoID, "Z");
-#endif
-		if (Conf_OperCanMode)
-			strcat(NGIRCd_ProtoID, "o");
-#else /* IRCPLUS */
-		snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
-			 PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
-#endif /* IRCPLUS */
-		strlcat(NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID);
-#ifdef ZLIB
-		strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
-#endif
-		LogDebug("Protocol and server ID is \"%s\".", NGIRCd_ProtoID);
+		LogDebug("Protocol and server ID is \"%s\".",
+			 Conn_BuildProtoID(-1));
 
 		Channel_InitPredefined();
 
-- 
1.7.10.2 (Apple Git-33)

