X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/15036dd60cda8df339bdbdcfc837d219082ae342..34f0ab116ad7734e96127d3cd046861a5c82c11c:/sbr/netsec.c diff --git a/sbr/netsec.c b/sbr/netsec.c index d76856e0..eb28cbac 100644 --- a/sbr/netsec.c +++ b/sbr/netsec.c @@ -108,17 +108,26 @@ static int checkascii(const unsigned char *byte, size_t len); /* * How this code works, in general. * - * _If_ we are using no encryption or SASL encryption, then we buffer the - * network data through ns_inbuffer and ns_outbuffer. That should be - * relatively self-explanatory. + * _If_ we are using no encryption then we buffer the network data + * through ns_inbuffer and ns_outbuffer. That should be relatively + * self-explanatory. * - * If we are using SSL for encryption, then use a buffering BIO for output - * (that just easier). Still do buffering for reads; when we need more - * data we call the BIO_read() function to fill our local buffer. + * If we use encryption, then ns_inbuffer and ns_outbuffer contain the + * cleartext data. When it comes time to send the encrypted data on the + * (either from a flush or the buffer is full) we either use BIO_write() + * for TLS or sasl_encode() (followed by a write() for Cyrus-SASL. For + * reads we either use BIO_read() (TLS) or do a network read into a + * temporary buffer and use sasl_decode() (Cyrus-SASL). Note that if + * negotiate TLS then we disable SASL encryption. * - * For SASL, we make use of (for now) the Cyrus-SASL library. For some - * mechanisms, we implement those mechanisms directly since the Cyrus SASL - * library doesn't support them (like OAuth). + * We used to use a buffering BIO for the reads/writes for TLS, but it + * ended up being complicated to special-case the buffering for everything + * except TLS, so the buffering is now unified, no matter which encryption + * method is being used (even none). + * + * For SASL authentication, we make use of (for now) the Cyrus-SASL + * library. For some mechanisms, we implement those mechanisms directly + * since the Cyrus SASL library doesn't support them (like OAuth). */ /* @@ -550,10 +559,38 @@ retry: */ } + /* + * Some explanation: + * + * startoffset is the offset from the beginning of the input + * buffer to data that is in our input buffer, but has not yet + * been consumed. This can be non-zero if functions like + * netsec_readline() leave leftover data. + * + * remaining is the remaining amount of unconsumed data in the input + * buffer. + * + * end is a pointer to the end of the valid data + 1; it's where + * the next read should go. + */ + startoffset = nsc->ns_inptr - nsc->ns_inbuffer; remaining = nsc->ns_inbufsize - (startoffset + nsc->ns_inbuflen); end = nsc->ns_inptr + nsc->ns_inbuflen; + /* + * If we're past the halfway point in our read buffers, shuffle everything + * back to the beginning. + */ + + if (startoffset > nsc->ns_inbufsize / 2) { + memmove(nsc->ns_inbuffer, nsc->ns_inptr, nsc->ns_inbuflen); + nsc->ns_inptr = nsc->ns_inbuffer; + startoffset = 0; + remaining = nsc->ns_inbufsize - nsc->ns_inbuflen; + end = nsc->ns_inptr + nsc->ns_inbuflen; + } + /* * If we are using TLS, then just read via the BIO. But we still * use our local buffer. @@ -588,7 +625,7 @@ retry: netsec_err(errstr, "TLS peer closed remote connection"); } else { netsec_err(errstr, "TLS network read failed: %s", - ERR_error_string(errcode, NULL)); + ERR_error_string(ERR_peek_last_error(), NULL)); } if (nsc->ns_snoop) ERR_print_errors_fp(stderr); @@ -679,16 +716,6 @@ retry: #endif /* CYRUS_SASL */ nsc->ns_inbuflen += rc; - /* - * If we're past the halfway point in our read buffers, shuffle everything - * back to the beginning. - */ - - if (startoffset > nsc->ns_inbufsize / 2) { - memmove(nsc->ns_inbuffer, nsc->ns_inptr, nsc->ns_inbuflen); - nsc->ns_inptr = nsc->ns_inbuffer; - } - return OK; }