- while (retbufsize == 0) {
-
- cc = read(fileno(f), tmpbuf, sizeof(tmpbuf));
-
- if (cc == 0)
- return EOF;
-
- if (cc < 0) {
- snprintf(response, sizeof(response), "Error during read from "
- "network: %s", strerror(errno));
- return -2;
- }
-
- /*
- * We're not allowed to call sasl_decode until sasl_complete is
- * true, so we do these gyrations ...
- */
-
- if (!sasl_complete) {
-
- retbuf = tmpbuf;
- retbufsize = cc;
-
- } else {
-
- result = sasl_decode(conn, tmpbuf, cc,
- (const char **) &retbuf, &retbufsize);
-
- if (result != SASL_OK) {
- snprintf(response, sizeof(response), "Error during SASL "
- "decoding: %s", sasl_errdetail(conn));
- return -2;
- }
- }
- }
-
- if (retbufsize > size) {
- buffer = mh_xrealloc(buffer, retbufsize);
- size = retbufsize;
- }
-
- memcpy(buffer, retbuf, retbufsize);
- ptr = buffer + 1;
- cnt = retbufsize - 1;
-
- return (int) buffer[0];
-}
-#endif /* CYRUS_SASL */
-
-#ifdef TLS_SUPPORT
-/*
- * Negotiate TLS at this point. Will call pop_done() on failure.
- */
-
-static int
-tls_negotiate(void)
-{
- BIO *ssl_bio;
-
- if (! sslctx) {
- SSL_METHOD *method;
-
- SSL_library_init();
- SSL_load_error_strings();
-
- method = TLS_client_method();
-
- sslctx = SSL_CTX_new(method);
-
- if (! sslctx()) {
- pop_done();
- advise(NULL, "Unable to initialize OpenSSL context: %s",
- ERR_error_string(ERR_get_error(), NULL));
- return NOTOK;
- }
- }
-
- ssl = SSL_new(sslctx);
-
- if (! ssl) {
- pop_done();
- advise(NULL, "Unable to create SSL connection: %s",
- ERR_error_string(ERR_get_error(), NULL));
- return NOTOK;
- }
-
- sbior = BIO_new_socket(fileno(input), BIO_NOCLOSE);
- sbiow = BIO_new_socket(fileno(output), BIO_NOCLOSE);
-
- if (sbior == NULL || sbiow == NULL) {
- pop_done();
- advise(NULL, "Unable to create BIO endpoints: %s",
- ERR_error_string(ERR_get_error(), NULL);
- return NOTOK;
- }
-
- SSL_set_bio(ssl, sbior, sbiow);
- SSL_set_connect_state(ssl);
-
- /*
- * Set up a BIO to do buffering for us
- */
-
- io = BIO_new(BIO_f_buffer());
-
- if (! io) {
- pop_done();
- advise(NULL, "Unable to create a buffer BIO: %s",
- ERR_error_string(ERR_get_error(), NULL);
- return NOTOK;
- }
-
- ssl_bio = BIO_new(BIO_f_ssl());
-
- if (! ssl_bio) {
- pop_done();
- advise(NULL, "Unable to create a SSL BIO: %s",
- ERR_error_string(ERR_get_error(), NULL);
- return NOTOK;
- }
-
- BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
- BIO_push(io, ssl_bio);
-
- /*
- * Try doing the handshake now
- */
-
- if (BIO_do_handshake(io) < 1) {
- pop_done();
- advise(NULL, "Unable to negotiate SSL connection: %s",
- ERR_error_string(ERR_get_error(), NULL);
- return NOTOK;
- }
-
- if (popprint) {
- const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
- printf("SSL negotiation successful: %s(%d) %s\n",
- SSL_CIPHER_get_name(cipher);
- SSL_CIPHER_get_bits(cipher, NULL);
- SSL_CIPHER_get_version(cipher);
- }
-
- tls_active = 1;