INN commit: trunk/nnrpd (line.c misc.c nnrpd.c)
INN Commit
rra at isc.org
Fri Dec 4 20:52:27 UTC 2015
Date: Friday, December 4, 2015 @ 12:52:27
Author: iulius
Revision: 9960
Improve the robustness of SASL handling
After sasl_decode(), add a check to prevent a call to memcpy() for 0
byte or for more bytes than the destination buffer.
Check that sasl_errdetail() does not return NULL.
Improve a few comments in the source code.
Modified:
trunk/nnrpd/line.c
trunk/nnrpd/misc.c
trunk/nnrpd/nnrpd.c
---------+
line.c | 46 +++++++++++++++++++++++++++++-----------------
misc.c | 6 +++---
nnrpd.c | 33 ++++++++++++++++++++-------------
3 files changed, 52 insertions(+), 33 deletions(-)
Modified: line.c
===================================================================
--- line.c 2015-11-03 19:55:06 UTC (rev 9959)
+++ line.c 2015-12-04 20:52:27 UTC (rev 9960)
@@ -119,24 +119,36 @@
if (n <= 0)
break; /* EOF or error. */
-#ifdef HAVE_SASL
- if (sasl_conn && sasl_ssf) {
- /* Security layer in place, decode the data. */
- const char *out;
- unsigned outlen;
- int r;
+#if defined(HAVE_SASL)
+ if (sasl_conn != NULL && sasl_ssf > 0) {
+ /* Security layer in place, decode the data.
+ * The incoming data is always encoded in chunks of length
+ * inferior or equal to NNTP_MAXLEN_COMMAND (the maxbufsize value
+ * of SASL_SEC_PROPS passed as part of the SASL exchange).
+ * So there's enough data to read in the p buffer. */
+ const char *out;
+ unsigned outlen;
+ int r;
+
+ if ((r = sasl_decode(sasl_conn, p, n, &out, &outlen)) == SASL_OK) {
+ if (outlen > len) {
+ sysnotice("sasl_decode() returned too much output");
+ n = -1;
+ } else {
+ if (outlen > 0) {
+ memcpy(p, out, outlen);
+ }
+ n = outlen;
+ }
+ } else {
+ const char *ed = sasl_errdetail(sasl_conn);
- if ((r = sasl_decode(sasl_conn, p, n, &out, &outlen)) == SASL_OK) {
- if (outlen)
- memcpy(p, out, outlen);
- n = outlen;
- } else {
- sysnotice("sasl_decode() failed: %s; %s",
- sasl_errstring(r, NULL, NULL),
- sasl_errdetail(sasl_conn));
- n = -1;
- }
- }
+ sysnotice("sasl_decode() failed: %s; %s",
+ sasl_errstring(r, NULL, NULL),
+ ed != NULL ? ed : "no detail");
+ n = -1;
+ }
+ }
#endif /* HAVE_SASL */
} while (n == 0); /* Split SASL blob, need to read more data. */
Modified: misc.c
===================================================================
--- misc.c 2015-11-03 19:55:06 UTC (rev 9959)
+++ misc.c 2015-12-04 20:52:27 UTC (rev 9960)
@@ -460,7 +460,7 @@
bool boolval;
if (encryption_layer_on) {
- Reply("%d Already using an active TLS layer\r\n", NNTP_ERR_ACCESS);
+ Reply("%d Already using a TLS layer\r\n", NNTP_ERR_ACCESS);
return;
}
@@ -519,7 +519,7 @@
ExitWithStats(1, false);
}
-#ifdef HAVE_SASL
+# if defined(HAVE_SASL)
/* Tell SASL about the negotiated layer. */
result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL,
(sasl_ssf_t *) &tls_cipher_usebits);
@@ -531,7 +531,7 @@
if (result != SASL_OK) {
syslog(L_NOTICE, "sasl_setprop() failed: CMDstarttls()");
}
-#endif /* HAVE_SASL */
+# endif /* HAVE_SASL */
/* Reset our read buffer so as to prevent plaintext command injection. */
line_reset(&NNTPline);
Modified: nnrpd.c
===================================================================
--- nnrpd.c 2015-11-03 19:55:06 UTC (rev 9959)
+++ nnrpd.c 2015-12-04 20:52:27 UTC (rev 9960)
@@ -36,6 +36,7 @@
#if defined(HAVE_OPENSSL)
extern SSL *tls_conn;
#endif
+
#if defined(HAVE_OPENSSL) || defined(HAVE_SASL)
bool encryption_layer_on = false;
#endif
@@ -439,12 +440,15 @@
Printf("READER\r\n");
-#ifdef HAVE_SASL
- /* Check whether at least one SASL mechanism is available. */
+#if defined(HAVE_SASL)
+ /* Check whether at least one SASL mechanism is available.
+ * The SASL capability has to be advertised, even after authentication,
+ * so that the client can detect a possible active down-negotiation
+ * attack. */
if (mechlist != NULL && strlen(mechlist) > 2) {
Printf("SASL%s\r\n", mechlist);
}
-#endif
+#endif /* HAVE_SASL */
#ifdef HAVE_OPENSSL
/* A TLS layer is not active and the client is not already authenticated. */
@@ -640,18 +644,21 @@
const char *out;
unsigned outlen;
-#ifdef HAVE_SASL
- if (sasl_conn && sasl_ssf) {
+#if defined(HAVE_SASL)
+ if (sasl_conn != NULL && sasl_ssf > 0) {
int r;
- /* Can only encode as much as the client can handle at one time. */
- n = (len > sasl_maxout) ? sasl_maxout : len;
- if ((r = sasl_encode(sasl_conn, p, n, &out, &outlen)) != SASL_OK) {
- sysnotice("sasl_encode() failed: %s",
- sasl_errstring(r, NULL, NULL));
- return;
- }
- } else
+ /* Can only encode as much as the client can handle at one time. */
+ n = (len > sasl_maxout) ? sasl_maxout : len;
+ if ((r = sasl_encode(sasl_conn, p, n, &out, &outlen)) != SASL_OK) {
+ const char *ed = sasl_errdetail(sasl_conn);
+
+ sysnotice("sasl_encode() failed: %s; %s",
+ sasl_errstring(r, NULL, NULL),
+ ed != NULL ? ed : "no detail");
+ return;
+ }
+ } else
#endif /* HAVE_SASL */
{
/* Output the entire unencoded string. */
More information about the inn-committers
mailing list