acl/libacls.la \
DiskIO/libdiskio.la \
acl/libapi.la \
+ anyp/libanyp.la \
$(SSL_LIBS) \
ipc/libipc.la \
comm/libcomm.la \
- anyp/libanyp.la \
dns/libdns.la \
base/libbase.la \
ip/libip.la \
void
comm_lingering_close(int fd)
{
-#if USE_OPENSSL
- if (fd_table[fd].ssl)
- ssl_shutdown_method(fd_table[fd].ssl);
-#endif
+ Security::SessionClose(fd_table[fd].ssl);
if (shutdown(fd, 1) < 0) {
comm_close(fd);
comm_close(fd);
}
-#if USE_OPENSSL
void
-commStartSslClose(const FdeCbParams ¶ms)
+commStartTlsClose(const FdeCbParams ¶ms)
{
- assert(fd_table[params.fd].ssl);
- ssl_shutdown_method(fd_table[params.fd].ssl.get());
+ Security::SessionClose(fd_table[params.fd].ssl);
}
-#endif
void
comm_close_complete(const FdeCbParams ¶ms)
F->flags.close_request = true;
-#if USE_OPENSSL
if (F->ssl) {
- AsyncCall::Pointer startCall=commCbCall(5,4, "commStartSslClose",
- FdeCbPtrFun(commStartSslClose, NULL));
+ AsyncCall::Pointer startCall=commCbCall(5,4, "commStartTlsClose",
+ FdeCbPtrFun(commStartTlsClose, nullptr));
FdeCbParams &startParams = GetCommParams<FdeCbParams>(startCall);
startParams.fd = fd;
ScheduleCallHere(startCall);
}
-#endif
// a half-closed fd may lack a reader, so we stop monitoring explicitly
if (commHasHalfClosedMonitor(fd))
#if USE_OPENSSL
const int result = SSL_connect(fd_table[fd].ssl.get());
+#elif USE_GNUTLS
+ const int result = gnutls_handshake(fd_table[fd].ssl.get());
#else
const int result = -1;
#endif
// Log connection details, if any
recordNegotiationDetails();
noteNegotiationError(ret, ssl_error, ssl_lib_error);
+
+#elif USE_GNUTLS
+ // TODO: handle specific errors individually like above
+ if (gnutls_error_is_fatal(ret) == 0) {
+ noteWantRead();
+ return;
+ }
#endif
}
#include "anyp/PortCfg.h"
#include "base/RunnersRegistry.h"
#include "Debug.h"
+#include "fd.h"
#include "fde.h"
#include "ipc/MemMap.h"
#include "security/Session.h"
#define SSL_SESSION_ID_SIZE 32
#define SSL_SESSION_MAX_SIZE 10*1024
+#if USE_OPENSSL || USE_GNUTLS
+static int
+tls_read_method(int fd, char *buf, int len)
+{
+ auto session = fd_table[fd].ssl.get();
+
+#if DONT_DO_THIS && USE_OPENSSL
+ if (!SSL_is_init_finished(session)) {
+ errno = ENOTCONN;
+ return -1;
+ }
+#endif
+
+#if USE_OPENSSL
+ int i = SSL_read(session, buf, len);
+#elif USE_GNUTLS
+ int i = gnutls_record_recv(session, buf, len);
+#endif
+ if (i > 0) {
+ (void)VALGRIND_MAKE_MEM_DEFINED(buf, i);
+ }
+
+#if USE_OPENSSL
+ if (i > 0 && SSL_pending(session) > 0) {
+#elif USE_GNUTLS
+ if (i > 0 && gnutls_record_check_pending(session) > 0) {
+#endif
+ debugs(83, 2, "TLS FD " << fd << " is pending");
+ fd_table[fd].flags.read_pending = true;
+ } else
+ fd_table[fd].flags.read_pending = false;
+
+ return i;
+}
+
+static int
+tls_write_method(int fd, const char *buf, int len)
+{
+ auto session = fd_table[fd].ssl.get();
+
+#if USE_OPENSSL
+ if (!SSL_is_init_finished(session)) {
+ errno = ENOTCONN;
+ return -1;
+ }
+#endif
+
+#if USE_OPENSSL
+ int i = SSL_write(session, buf, len);
+#elif USE_GNUTLS
+ int i = gnutls_record_send(session, buf, len);
+#endif
+
+ return i;
+}
+#endif
+
static bool
CreateSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Security::Io::Type type, const char *squidCtx)
{
return false;
}
+#if USE_OPENSSL || USE_GNUTLS
+
const char *errAction = "with no TLS/SSL library";
int errCode = 0;
#if USE_OPENSSL
- Security::SessionPointer ssl(SSL_new(ctx.get()));
- if (ssl) {
+ Security::SessionPointer session(SSL_new(ctx.get()));
+ if (!session) {
+ errCode = ERR_get_error();
+ errAction = "failed to allocate handle";
+ }
+#elif USE_GNUTLS
+ gnutls_session_t tmp;
+ errCode = gnutls_init(&tmp, static_cast<unsigned int>(type));
+ Security::SessionPointer session(tmp);
+ if (errCode != GNUTLS_E_SUCCESS) {
+ session.reset();
+ errAction = "failed to initialize session";
+ }
+#endif
+
+ if (session) {
const int fd = conn->fd;
+
+#if USE_OPENSSL
// without BIO, we would call SSL_set_fd(ssl.get(), fd) instead
if (BIO *bio = Ssl::Bio::Create(fd, type)) {
- Ssl::Bio::Link(ssl.get(), bio); // cannot fail
+ Ssl::Bio::Link(session.get(), bio); // cannot fail
+#elif USE_GNUTLS
+ errCode = gnutls_credentials_set(session.get(), GNUTLS_CRD_CERTIFICATE, ctx.get());
+ if (errCode == GNUTLS_E_SUCCESS) {
+#endif
- fd_table[fd].ssl = ssl;
- fd_table[fd].read_method = &ssl_read_method;
- fd_table[fd].write_method = &ssl_write_method;
+ fd_table[fd].ssl = session;
+ fd_table[fd].read_method = &tls_read_method;
+ fd_table[fd].write_method = &tls_write_method;
fd_note(fd, squidCtx);
return true;
}
+
+#if USE_OPENSSL
errCode = ERR_get_error();
errAction = "failed to initialize I/O";
- } else {
- errCode = ERR_get_error();
- errAction = "failed to allocate handle";
- }
+#elif USE_GNUTLS
+ errAction = "failed to assign credentials";
#endif
+ }
+
debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
": " << (errCode != 0 ? Security::ErrorString(errCode) : ""));
+#endif
return false;
}
return CreateSession(ctx, c, Security::Io::BIO_TO_CLIENT, squidCtx);
}
+void
+Security::SessionClose(const Security::SessionPointer &s)
+{
+ debugs(83, 5, "session=" << (void*)s.get());
+ if (s) {
+#if USE_OPENSSL
+ SSL_shutdown(s.get());
+#elif USE_GNUTLS
+ gnutls_bye(s.get(), GNUTLS_SHUT_RDWR);
+#endif
+ }
+}
+
bool
Security::SessionIsResumed(const Security::SessionPointer &s)
{
#endif
+/// close an active TLS session
+void SessionClose(const Security::SessionPointer &);
+
/// whether the session is a resumed one
bool SessionIsResumed(const Security::SessionPointer &);
namespace Io
{
enum Type {
+#if USE_GNUTLS
+ BIO_TO_CLIENT = GNUTLS_CLIENT,
+ BIO_TO_SERVER = GNUTLS_SERVER
+#else
BIO_TO_CLIENT = 6000,
BIO_TO_SERVER
+#endif
};
} // namespace Io
return true;
}
-/// \ingroup ServerProtocolSSLInternal
-int
-ssl_read_method(int fd, char *buf, int len)
-{
- auto ssl = fd_table[fd].ssl.get();
-
-#if DONT_DO_THIS
-
- if (!SSL_is_init_finished(ssl)) {
- errno = ENOTCONN;
- return -1;
- }
-
-#endif
-
- int i = SSL_read(ssl, buf, len);
- if (i > 0) {
- (void)VALGRIND_MAKE_MEM_DEFINED(buf, i);
- }
-
- if (i > 0 && SSL_pending(ssl) > 0) {
- debugs(83, 2, "SSL FD " << fd << " is pending");
- fd_table[fd].flags.read_pending = true;
- } else
- fd_table[fd].flags.read_pending = false;
-
- return i;
-}
-
-/// \ingroup ServerProtocolSSLInternal
-int
-ssl_write_method(int fd, const char *buf, int len)
-{
- auto ssl = fd_table[fd].ssl.get();
- if (!SSL_is_init_finished(ssl)) {
- errno = ENOTCONN;
- return -1;
- }
-
- int i = SSL_write(ssl, buf, len);
- return i;
-}
-
-void
-ssl_shutdown_method(SSL *ssl)
-{
- SSL_shutdown(ssl);
-}
-
/// \ingroup ServerProtocolSSLInternal
static const char *
ssl_get_attribute(X509_NAME * name, const char *attribute_name)
} //namespace Ssl
-/// \ingroup ServerProtocolSSLAPI
-int ssl_read_method(int, char *, int);
-
-/// \ingroup ServerProtocolSSLAPI
-int ssl_write_method(int, const char *, int);
-
-/// \ingroup ServerProtocolSSLAPI
-void ssl_shutdown_method(SSL *ssl);
-
/// \ingroup ServerProtocolSSLAPI
const char *sslGetUserEmail(SSL *ssl);
namespace Security {
bool CreateClientSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *) STUB_RETVAL(false)
bool CreateServerSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *) STUB_RETVAL(false)
+void SessionClose(const Security::SessionPointer &) STUB
bool SessionIsResumed(const Security::SessionPointer &) STUB_RETVAL(false)
void MaybeGetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &) STUB
void SetSessionResumeData(const Security::SessionPointer &, const Security::SessionStatePointer &) STUB
bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &) STUB_RETVAL(false)
bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long, const char *) STUB_RETVAL(false)
} // namespace Ssl
-int ssl_read_method(int, char *, int) STUB_RETVAL(0)
-int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
-void ssl_shutdown_method(SSL *ssl) STUB
const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)