Exemple #1
0
int sock_make_secure(nsocket *sock, nssl_context *ctx)
{
#ifdef ENABLE_SSL
    int ret;
    SSL_CTX *ssl_ctx;

    if (ctx) {
	ssl_ctx = ctx->ctx;
    } else {
	ssl_ctx = sock->default_ctx;
    }

    sock->ssl = SSL_new(ssl_ctx);
    if (!sock->ssl) {
	sock->error = ERROR_SSL_STRING;
	/* Usually goes wrong because: */
	fprintf(stderr, "Have you called sock_init()!?\n");
	return SOCK_ERROR;
    }
    
    SSL_set_fd(sock->ssl, sock->fd);
    
    ret = SSL_connect(sock->ssl);
    if (ret == -1) {
	sock->error = ERROR_SSL_STRING;
	SSL_free(sock->ssl);
	sock->ssl = NULL;
	return SOCK_ERROR;
    }

#if 0
    /* Tommi Komulainen <[email protected]> has donated his SSL
     * cert verification from the mutt IMAP/SSL code under the
     * LGPL... it will plug in here */
    ret = sock_check_certicate(sock);
    if (ret) {
	SSL_shutdown(sock->ssl);
	SSL_free(sock->ssl);
	sock->ssl = NULL;
	return ret;
    }
#endif

    if (notify_cb) (*notify_cb)(notify_ud, sock_secure_details, 
				  SSL_get_version(sock->ssl));
    DEBUG(DEBUG_SOCKET, "SSL connected: version %s\n", 
	   SSL_get_version(sock->ssl));
    return 0;
#else
    sock->error = _("This application does not have SSL support.");
    return SOCK_ERROR;
#endif
}
Exemple #2
0
Datum
ssl_version(PG_FUNCTION_ARGS)
{
	if (MyProcPort->ssl == NULL)
		PG_RETURN_NULL();
	PG_RETURN_TEXT_P(cstring_to_text(SSL_get_version(MyProcPort->ssl)));
}
Exemple #3
0
static int get_version(str* res, sip_msg_t* msg)
{
	str version;
	static char buf[1024];

	struct tcp_connection* c;
	SSL* ssl;

	c = get_cur_connection(msg);
	if (!c) {
		INFO("TLS connection not found in select_version\n");
		goto err;
	}
	ssl = get_ssl(c);
	if (!ssl) goto err;

	version.s = (char*)SSL_get_version(ssl);
	version.len = version.s ? strlen(version.s) : 0;
	if (version.len >= 1024) {
		ERR("Version string too long\n");
		goto err;
	}
	memcpy(buf, version.s, version.len);
	res->s = buf;
	res->len = version.len;
	tcpconn_put(c);
        return 0;

 err:
	if (c) tcpconn_put(c);
	return -1;
}
Exemple #4
0
static const char *
openssl_iostream_get_security_string(struct ssl_iostream *ssl_io)
{
    const SSL_CIPHER *cipher;
#ifdef HAVE_SSL_COMPRESSION
    const COMP_METHOD *comp;
#endif
    const char *comp_str;
    int bits, alg_bits;

    if (!ssl_io->handshaked)
        return "";

    cipher = SSL_get_current_cipher(ssl_io->ssl);
    bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
#ifdef HAVE_SSL_COMPRESSION
    comp = SSL_get_current_compression(ssl_io->ssl);
    comp_str = comp == NULL ? "" :
               t_strconcat(" ", SSL_COMP_get_name(comp), NULL);
#else
    comp_str = "";
#endif
    return t_strdup_printf("%s with cipher %s (%d/%d bits)%s",
                           SSL_get_version(ssl_io->ssl),
                           SSL_CIPHER_get_name(cipher),
                           bits, alg_bits, comp_str);
}
Exemple #5
0
const char*
io_strio(struct io *io)
{
	static char	buf[128];
	char		ssl[128];

	ssl[0] = '\0';
#ifdef IO_SSL
	if (io->ssl) {
		(void)snprintf(ssl, sizeof ssl, " ssl=%s:%s:%d",
		    SSL_get_version(io->ssl),
		    SSL_get_cipher_name(io->ssl),
		    SSL_get_cipher_bits(io->ssl, NULL));
	}
#endif

	if (io->iobuf == NULL)
		(void)snprintf(buf, sizeof buf,
		    "<io:%p fd=%d to=%d fl=%s%s>",
		    io, io->sock, io->timeout, io_strflags(io->flags), ssl);
	else
		(void)snprintf(buf, sizeof buf,
		    "<io:%p fd=%d to=%d fl=%s%s ib=%zu ob=%zu>",
		    io, io->sock, io->timeout, io_strflags(io->flags), ssl,
		    io_pending(io), io_queued(io));

	return (buf);
}
Exemple #6
0
int
tls_get_conninfo(struct tls *ctx) {
	const char * tmp;

	tls_free_conninfo(ctx->conninfo);

	if (ctx->ssl_peer_cert != NULL) {
		if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1)
			goto err;
		if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject)
		    == -1)
			goto err;
		if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1)
			goto err;
		if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore,
		    &ctx->conninfo->notafter) == -1)
			goto err;
	}
	if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
		goto err;
	ctx->conninfo->version = strdup(tmp);
	if (ctx->conninfo->version == NULL)
		goto err;
	if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
		goto err;
	ctx->conninfo->cipher = strdup(tmp);
	if (ctx->conninfo->cipher == NULL)
		goto err;
	return (0);
err:
	tls_free_conninfo(ctx->conninfo);
	return (-1);
}
Exemple #7
0
/**
 * Callback used for debugging
 */
static void sslLogCallback(const SSL *ssl, int where, int ret) {
    const char *retstr = "";
    int should_log = 1;
    /* Ignore low-level SSL stuff */

    if (where & SSL_CB_ALERT) {
        should_log = 1;
    }
    if (where == SSL_CB_HANDSHAKE_START || where == SSL_CB_HANDSHAKE_DONE) {
        should_log = 1;
    }
    if ((where & SSL_CB_EXIT) && ret == 0) {
        should_log = 1;
    }

    if (!should_log) {
        return;
    }

    retstr = SSL_alert_type_string(ret);
    printf("ST(0x%x). %s. R(0x%x)%s\n", where, SSL_state_string_long(ssl), ret, retstr);

    if (where == SSL_CB_HANDSHAKE_DONE) {
        printf("Using SSL version %s. Cipher=%s\n", SSL_get_version(ssl), SSL_get_cipher_name(ssl));
    }
}
Exemple #8
0
datum_t
ssl_version(PG_FUNC_ARGS)
{
	if (proc_port->ssl == NULL)
		RET_NULL();
	RET_TEXT_P(cstring_to_text(SSL_get_version(proc_port->ssl)));
}
const char *
be_tls_get_version(Port *port)
{
	if (port->ssl)
		return SSL_get_version(port->ssl);
	else
		return NULL;
}
void
be_tls_get_version(Port *port, char *ptr, size_t len)
{
	if (port->ssl)
		strlcpy(ptr, SSL_get_version(port->ssl), len);
	else
		ptr[0] = '\0';
}
Exemple #11
0
std::string SSLSocket::getEncryptionInfo() const noexcept {
	if (!ssl)
		return Util::emptyString;

	string cipher = SSL_get_cipher_name(ssl);
	string protocol = SSL_get_version(ssl);
	return protocol + " / " + cipher;
}
Exemple #12
0
static void set_cipher_info(TLS_REC *tls, SSL *ssl)
{
	g_return_if_fail(tls != NULL);
	g_return_if_fail(ssl != NULL);

	tls_rec_set_protocol_version(tls, SSL_get_version(ssl));

	tls_rec_set_cipher(tls, SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)));
	tls_rec_set_cipher_size(tls, SSL_get_cipher_bits(ssl, NULL));
}
Exemple #13
0
void describeConnection(SSL* ssl)
{
  char buff[128];
  const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
  CHECK(cipher != NULL);
  char *desc = SSL_CIPHER_description(cipher,buff,128);
  CHECK(desc != NULL);
  fprintf(stderr,"renegotiation: %s\n",
          SSL_get_secure_renegotiation_support(ssl)?"allowed":"disallowed");  
  fprintf(stderr,"%s: %s", SSL_get_version(ssl), desc);
}
Exemple #14
0
const char *
ssl_to_text(const SSL *ssl)
{
	static char buf[256];

	(void)snprintf(buf, sizeof buf, "version=%s, cipher=%s, bits=%d",
	    SSL_get_version(ssl),
	    SSL_get_cipher_name(ssl),
	    SSL_get_cipher_bits(ssl, NULL));

	return (buf);
}
   CipherInfo
   TCPConnection::GetCipherInfo()
   {
      if (!is_ssl_)
      {
         throw std::logic_error("Session is not SSL/TLS. Cipher info cannot be retrieved.");
      }

      auto ssl_handle = ssl_socket_.native_handle();
      AnsiString name = SSL_get_cipher_name(ssl_handle);
      AnsiString version = SSL_get_version(ssl_handle);
      int bits = SSL_get_cipher_bits(ssl_handle, 0);
      return CipherInfo(name, version, bits);
   }
Exemple #16
0
ssize_t
tls_get_connection_info(struct tls *ctx, char *buf, size_t buflen)
{
	SSL *conn = ctx->ssl_conn;
	const char *ocsp_pfx = "", *ocsp_info = "";
	const char *proto = "-", *cipher = "-";
	char dh[64];
	int used_dh_bits = ctx->used_dh_bits, used_ecdh_nid = ctx->used_ecdh_nid;

	if (conn != NULL) {
		proto = SSL_get_version(conn);
		cipher = SSL_get_cipher(conn);

#ifdef SSL_get_server_tmp_key
		if (ctx->flags & TLS_CLIENT) {
			EVP_PKEY *pk = NULL;
			int ok = SSL_get_server_tmp_key(conn, &pk);
			int pk_type = EVP_PKEY_id(pk);
			if (ok && pk) {
				if (pk_type == EVP_PKEY_DH) {
					DH *dh = EVP_PKEY_get0(pk);
					used_dh_bits = DH_size(dh) * 8;
				} else if (pk_type == EVP_PKEY_EC) {
					EC_KEY *ecdh = EVP_PKEY_get0(pk);
					const EC_GROUP *eg = EC_KEY_get0_group(ecdh);
					used_ecdh_nid = EC_GROUP_get_curve_name(eg);
				}
				EVP_PKEY_free(pk);
			}
		}
#endif
	}

	if (used_dh_bits) {
		snprintf(dh, sizeof dh, "/DH=%d", used_dh_bits);
	} else if (used_ecdh_nid) {
		snprintf(dh, sizeof dh, "/ECDH=%s", OBJ_nid2sn(used_ecdh_nid));
	} else {
		dh[0] = 0;
	}

	if (ctx->ocsp_result) {
		ocsp_info = ctx->ocsp_result;
		ocsp_pfx = "/OCSP=";
	}

	return snprintf(buf, buflen, "%s/%s%s%s%s", proto, cipher, dh, ocsp_pfx, ocsp_info);
}
Exemple #17
0
/* ssl_negotiate: After SSL state has been initialised, attempt to negotiate
 *   SSL over the wire, including certificate checks. */
static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata)
{
  int err;
  const char* errmsg;

#if OPENSSL_VERSION_NUMBER >= 0x00906000L
  /* This only exists in 0.9.6 and above. Without it we may get interrupted
   *   reads or writes. Bummer. */
  SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY);
#endif

  if ((err = SSL_connect (ssldata->ssl)) != 1)
  {
    switch (SSL_get_error (ssldata->ssl, err))
    {
    case SSL_ERROR_SYSCALL:
      errmsg = _("I/O error");
      break;
    case SSL_ERROR_SSL:
      errmsg = ERR_error_string (ERR_get_error (), NULL);
      break;
    default:
      errmsg = _("unknown error");
    }

    mutt_error (_("SSL failed: %s"), errmsg);
    mutt_sleep (1);

    return -1;
  }

  ssldata->cert = SSL_get_peer_certificate (ssldata->ssl);
  if (!ssldata->cert)
  {
    mutt_error (_("Unable to get certificate from peer"));
    mutt_sleep (1);
    return -1;
  }

  if (!ssl_check_certificate (conn, ssldata))
    return -1;

  mutt_message (_("%s connection using %s (%s)"),
    SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl));
  mutt_sleep (0);

  return 0;
}
Exemple #18
0
/* ssl_negotiate: After SSL state has been initialized, attempt to negotiate
 *   SSL over the wire, including certificate checks. */
static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata)
{
  int err;
  const char* errmsg;

  SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY);

  if ((err = SSL_connect (ssldata->ssl)) != 1)
  {
    switch (SSL_get_error (ssldata->ssl, err))
    {
    case SSL_ERROR_SYSCALL:
      errmsg = _("I/O error");
      break;
    case SSL_ERROR_SSL:
      errmsg = ERR_error_string (ERR_get_error (), NULL);
      break;
    default:
      errmsg = _("unknown error");
    }

    mutt_error (_("SSL failed: %s"), errmsg);
    mutt_sleep (1);

    return -1;
  }

  ssldata->cert = SSL_get_peer_certificate (ssldata->ssl);
  if (!ssldata->cert)
  {
    mutt_error (_("Unable to get certificate from peer"));
    mutt_sleep (1);
    return -1;
  }

  if (!ssl_check_certificate (conn, ssldata))
    return -1;

  /* L10N:
     %1$s is version (e.g. "TLSv1.2")
     %2$s is cipher_version (e.g. "TLSv1/SSLv3")
     %3$s is cipher_name (e.g. "ECDHE-RSA-AES128-GCM-SHA256") */
  mutt_message (_("%s connection using %s (%s)"),
    SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl));
  mutt_sleep (0);

  return 0;
}
Exemple #19
0
/**
 * Return information about the connection.
 */
static int meth_info(lua_State *L)
{
  int bits = 0;
  int algbits = 0;
  char buf[256] = {0};
  const SSL_CIPHER *cipher;
  p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
  cipher = SSL_get_current_cipher(ssl->ssl);
  if (!cipher)
    return 0;
  SSL_CIPHER_description(cipher, buf, sizeof(buf));
  bits = SSL_CIPHER_get_bits(cipher, &algbits);
  lua_pushstring(L, buf);
  lua_pushnumber(L, bits);
  lua_pushnumber(L, algbits);
  lua_pushstring(L, SSL_get_version(ssl->ssl));
  return 4;
}
Exemple #20
0
static void print_details(SSL *c_ssl, const char *prefix)
	{
	SSL_CIPHER *ciph;
	X509 *cert;
		
	ciph=SSL_get_current_cipher(c_ssl);
	BIO_printf(bio_stdout,"%s%s, cipher %s %s",
		prefix,
		SSL_get_version(c_ssl),
		SSL_CIPHER_get_version(ciph),
		SSL_CIPHER_get_name(ciph));
	cert=SSL_get_peer_certificate(c_ssl);
	if (cert != NULL)
		{
		EVP_PKEY *pkey = X509_get_pubkey(cert);
		if (pkey != NULL)
			{
			if (0) 
				;
#ifndef OPENSSL_NO_RSA
			else if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL
				&& pkey->pkey.rsa->n != NULL)
				{
				BIO_printf(bio_stdout, ", %d bit RSA",
					BN_num_bits(pkey->pkey.rsa->n));
				}
#endif
#ifndef OPENSSL_NO_DSA
			else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL
				&& pkey->pkey.dsa->p != NULL)
				{
				BIO_printf(bio_stdout, ", %d bit DSA",
					BN_num_bits(pkey->pkey.dsa->p));
				}
#endif
			EVP_PKEY_free(pkey);
			}
		X509_free(cert);
		}
	/* The SSL API does not allow us to look at temporary RSA/DH keys,
	 * otherwise we should print their lengths too */
	BIO_printf(bio_stdout,"\n");
	}
Exemple #21
0
int ssl_session_vars(SSL *ssl) {
  char *x;
  SSL_SESSION *session;
  int n;
  int m;
  const SSL_CIPHER *cipher;
  unsigned char u;
  unsigned char c;

  if (!env_str("SSL_PROTOCOL",SSL_get_version(ssl)))
    return 0;

  session = SSL_get_session(ssl);
  x = session->session_id;
  n = session->session_id_length;
  if (!stralloc_ready(&btemp,2 * n)) return 0;
  btemp.len = 2 * n;
  while (n--) {
    u = x[n];
    c = '0' + (u & 15); if (c > '0' + 9) c += 'a' - '0' - 10;
    btemp.s[2 * n + 1] = c;
    u >>= 4;
    c = '0' + (u & 15); if (c > '0' + 9) c += 'a' - '0' - 10;
    btemp.s[2 * n] = c;
  }
  if (!env_val("SSL_SESSION_ID",btemp.s,btemp.len)) return 0;

  if (!env_str("SSL_CIPHER",SSL_get_cipher_name(ssl))) return 0;
  
  cipher = SSL_get_current_cipher(ssl);
  if (!cipher) return 0;
  n = SSL_CIPHER_get_bits(cipher,&m);
  if (!env_str("SSL_CIPHER_EXPORT",n < 56 ? "true" : "false")) return 0;
  if (!env_val("SSL_CIPHER_USEKEYSIZE",strnum,fmt_ulong(strnum,n))) return 0;
  if (!env_val("SSL_CIPHER_ALGKEYSIZE",strnum,fmt_ulong(strnum,m))) return 0;

  if (!env_str("SSL_VERSION_INTERFACE","ucspi-ssl")) return 0;
  if (!env_str("SSL_VERSION_LIBRARY",OPENSSL_VERSION_TEXT)) return 0;

  return 1;
}
Exemple #22
0
/* **************************************
 *
 * Information functions
 *
 * Print information for the end user.
 *
 ***************************************/
void
print_details (struct key_state_ssl * ks_ssl, const char *prefix)
{
  const SSL_CIPHER *ciph;
  X509 *cert;
  char s1[256];
  char s2[256];

  s1[0] = s2[0] = 0;
  ciph = SSL_get_current_cipher (ks_ssl->ssl);
  openvpn_snprintf (s1, sizeof (s1), "%s %s, cipher %s %s",
		    prefix,
		    SSL_get_version (ks_ssl->ssl),
		    SSL_CIPHER_get_version (ciph),
		    SSL_CIPHER_get_name (ciph));
  cert = SSL_get_peer_certificate (ks_ssl->ssl);
  if (cert != NULL)
    {
      EVP_PKEY *pkey = X509_get_pubkey (cert);
      if (pkey != NULL)
	{
	  if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL
	      && pkey->pkey.rsa->n != NULL)
	    {
	      openvpn_snprintf (s2, sizeof (s2), ", %d bit RSA",
				BN_num_bits (pkey->pkey.rsa->n));
	    }
	  else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL
		   && pkey->pkey.dsa->p != NULL)
	    {
	      openvpn_snprintf (s2, sizeof (s2), ", %d bit DSA",
				BN_num_bits (pkey->pkey.dsa->p));
	    }
	  EVP_PKEY_free (pkey);
	}
      X509_free (cert);
    }
  /* The SSL API does not allow us to look at temporary RSA/DH keys,
   * otherwise we should print their lengths too */
  msg (D_HANDSHAKE, "%s%s", s1, s2);
}
Exemple #23
0
/**
 * We directly initiate a TLS handshake with the server. If the server is old
 * version (does not speak TLS) the connection will be denied.
 * @note the socket file descriptor in #conn_info must be connected and *not*
 *       non-blocking
 * @return -1 in case of error
 */
int TLSTry(ConnectionInfo *conn_info)
{
    if (PRIVKEY == NULL || PUBKEY == NULL)
    {
        Log(LOG_LEVEL_ERR, "No public/private key pair is loaded,"
            " please create one using cf-key");
        return -1;
    }
    assert(SSLCLIENTCONTEXT != NULL);

    conn_info->ssl = SSL_new(SSLCLIENTCONTEXT);
    if (conn_info->ssl == NULL)
    {
        Log(LOG_LEVEL_ERR, "SSL_new: %s",
            TLSErrorString(ERR_get_error()));
        return -1;
    }

    /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */
    SSL_set_ex_data(conn_info->ssl, CONNECTIONINFO_SSL_IDX, conn_info);

    /* Initiate the TLS handshake over the already open TCP socket. */
    SSL_set_fd(conn_info->ssl, conn_info->sd);

    int ret = SSL_connect(conn_info->ssl);
    if (ret <= 0)
    {
        TLSLogError(conn_info->ssl, LOG_LEVEL_ERR,
                    "Failed to establish TLS connection", ret);
        return -1;
    }

    Log(LOG_LEVEL_VERBOSE, "TLS version negotiated: %8s; Cipher: %s,%s",
        SSL_get_version(conn_info->ssl),
        SSL_get_cipher_name(conn_info->ssl),
        SSL_get_cipher_version(conn_info->ssl));
    Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust...");

    return 0;
}
Exemple #24
0
static void
ConnSSL_LogCertInfo( CONNECTION *c )
{
#ifdef HAVE_LIBSSL
	SSL *ssl = c->ssl_state.ssl;

	assert(ssl);

	Log(LOG_INFO, "Connection %d: initialized %s using cipher %s.",
		c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl));
#endif
#ifdef HAVE_LIBGNUTLS
	gnutls_session_t sess = c->ssl_state.gnutls_session;
	gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);

	Log(LOG_INFO, "Connection %d: initialized %s using cipher %s-%s.",
	    c->sock,
	    gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
	    gnutls_cipher_get_name(cipher),
	    gnutls_mac_get_name(gnutls_mac_get(sess)));
#endif
}
Exemple #25
0
int tlsops_version(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	str version;
	static char buf[1024];

	struct tcp_connection* c;
	SSL* ssl;

	c = get_cur_connection(msg);
	if (!c) {
		LM_INFO("TLS connection not found in select_version\n");
		goto err;
	}
	ssl = get_ssl(c);
	if (!ssl) goto err;

	version.s = (char*)SSL_get_version(ssl);
	version.len = version.s ? strlen(version.s) : 0;
	if (version.len >= 1024) {
		LM_ERR("version string too long\n");
		goto err;
	}
	memcpy(buf, version.s, version.len);

	res->rs.s = buf;
	res->rs.len = version.len;
	res->flags = PV_VAL_STR;

	tcpconn_put(c);

	return 0;
err:
	if (c) tcpconn_put(c);
	return pv_get_null(msg, param, res);
}
Exemple #26
0
#ifdef USE_SSL
if (port->ssl)
    ereport(LOG,
            (errmsg("replication connection authorized: user=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)",
                    port->user_name, SSL_get_version(port->ssl), SSL_get_cipher(port->ssl),
                    SSL_get_current_compression(port->ssl) ? _("on") : _("off"))));
else
#endif
    ereport(LOG,
            (errmsg("replication connection authorized: user=%s",
                    port->user_name)));
Exemple #27
0
/*
 * PerformAuthentication -- authenticate a remote client
 *
 * returns: nothing.  Will not return at all if there's any failure.
 */
static void
PerformAuthentication(Port *port)
{
    /* This should be set already, but let's make sure */
    ClientAuthInProgress = true;	/* limit visibility of log messages */

    /*
     * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.conf
     * etcetera from the postmaster, and have to load them ourselves.
     *
     * FIXME: [fork/exec] Ugh.  Is there a way around this overhead?
     */
#ifdef EXEC_BACKEND
    if (!load_hba())
    {
        /*
         * It makes no sense to continue if we fail to load the HBA file,
         * since there is no way to connect to the database in this case.
         */
        ereport(FATAL,
                (errmsg("could not load pg_hba.conf")));
    }

    if (!load_ident())
    {
        /*
         * It is ok to continue if we fail to load the IDENT file, although it
         * means that you cannot log in using any of the authentication
         * methods that need a user name mapping. load_ident() already logged
         * the details of error to the log.
         */
    }
#endif

    /*
     * Set up a timeout in case a buggy or malicious client fails to respond
     * during authentication.  Since we're inside a transaction and might do
     * database access, we have to use the statement_timeout infrastructure.
     */
    enable_timeout_after(STATEMENT_TIMEOUT, AuthenticationTimeout * 1000);

    /*
     * Now perform authentication exchange.
     */
    ClientAuthentication(port); /* might not return, if failure */

    /*
     * Done with authentication.  Disable the timeout, and log if needed.
     */
    disable_timeout(STATEMENT_TIMEOUT, false);

    if (Log_connections)
    {
        if (am_walsender)
        {
#ifdef USE_SSL
            if (port->ssl)
                ereport(LOG,
                        (errmsg("replication connection authorized: user=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)",
                                port->user_name, SSL_get_version(port->ssl), SSL_get_cipher(port->ssl),
                                SSL_get_current_compression(port->ssl) ? _("on") : _("off"))));
            else
#endif
                ereport(LOG,
                        (errmsg("replication connection authorized: user=%s",
                                port->user_name)));
        }
        else
        {
#ifdef USE_SSL
            if (port->ssl)
                ereport(LOG,
                        (errmsg("connection authorized: user=%s database=%s SSL enabled (protocol=%s, cipher=%s, compression=%s)",
                                port->user_name, port->database_name, SSL_get_version(port->ssl), SSL_get_cipher(port->ssl),
                                SSL_get_current_compression(port->ssl) ? _("on") : _("off"))));
            else
#endif
                ereport(LOG,
                        (errmsg("connection authorized: user=%s database=%s",
                                port->user_name, port->database_name)));
        }
    }

    set_ps_display("startup", false);

    ClientAuthInProgress = false;		/* client_min_messages is active now */
}
Exemple #28
0
 /*
  * This is the actual startup routine for the connection. We expect that the
  * buffers are flushed and the "220 Ready to start TLS" was received by us,
  * so that we can immediately start the TLS handshake process.
  */
TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
{
    int     sts;
    int     protomask;
    const char *cipher_list;
    SSL_SESSION *session = 0;
    SSL_CIPHER_const SSL_CIPHER *cipher;
    X509   *peercert;
    TLS_SESS_STATE *TLScontext;
    TLS_APPL_STATE *app_ctx = props->ctx;
    char   *myserverid;
    int     log_mask = app_ctx->log_mask;

    /*
     * When certificate verification is required, log trust chain validation
     * errors even when disabled by default for opportunistic sessions. For
     * DANE this only applies when using trust-anchor associations.
     */
    if (TLS_MUST_TRUST(props->tls_level)
      && (!TLS_DANE_BASED(props->tls_level) || TLS_DANE_HASTA(props->dane)))
	log_mask |= TLS_LOG_UNTRUSTED;

    if (log_mask & TLS_LOG_VERBOSE)
	msg_info("setting up TLS connection to %s", props->namaddr);

    /*
     * First make sure we have valid protocol and cipher parameters
     * 
     * Per-session protocol restrictions must be applied to the SSL connection,
     * as restrictions in the global context cannot be cleared.
     */
    protomask = tls_protocol_mask(props->protocols);
    if (protomask == TLS_PROTOCOL_INVALID) {
	/* tls_protocol_mask() logs no warning. */
	msg_warn("%s: Invalid TLS protocol list \"%s\": aborting TLS session",
		 props->namaddr, props->protocols);
	return (0);
    }
    /* DANE requires SSLv3 or later, not SSLv2. */
    if (TLS_DANE_BASED(props->tls_level))
	protomask |= TLS_PROTOCOL_SSLv2;

    /*
     * Per session cipher selection for sessions with mandatory encryption
     * 
     * The cipherlist is applied to the global SSL context, since it is likely
     * to stay the same between connections, so we make use of a 1-element
     * cache to return the same result for identical inputs.
     */
    cipher_list = tls_set_ciphers(app_ctx, "TLS", props->cipher_grade,
				  props->cipher_exclusions);
    if (cipher_list == 0) {
	msg_warn("%s: %s: aborting TLS session",
		 props->namaddr, vstring_str(app_ctx->why));
	return (0);
    }
    if (log_mask & TLS_LOG_VERBOSE)
	msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list);

    /*
     * OpenSSL will ignore cached sessions that use the wrong protocol. So we
     * do not need to filter out cached sessions with the "wrong" protocol,
     * rather OpenSSL will simply negotiate a new session.
     * 
     * We salt the session lookup key with the protocol list, so that sessions
     * found in the cache are plausibly acceptable.
     * 
     * By the time a TLS client is negotiating ciphers it has already offered to
     * re-use a session, it is too late to renege on the offer. So we must
     * not attempt to re-use sessions whose ciphers are too weak. We salt the
     * session lookup key with the cipher list, so that sessions found in the
     * cache are always acceptable.
     * 
     * With DANE, (more generally any TLScontext where we specified explicit
     * trust-anchor or end-entity certificates) the verification status of
     * the SSL session depends on the specified list.  Since we verify the
     * certificate only during the initial handshake, we must segregate
     * sessions with different TA lists.  Note, that TA re-verification is
     * not possible with cached sessions, since these don't hold the complete
     * peer trust chain.  Therefore, we compute a digest of the sorted TA
     * parameters and append it to the serverid.
     */
    myserverid = tls_serverid_digest(props, protomask, cipher_list);

    /*
     * Allocate a new TLScontext for the new connection and get an SSL
     * structure. Add the location of TLScontext to the SSL to later retrieve
     * the information inside the tls_verify_certificate_callback().
     * 
     * If session caching was enabled when TLS was initialized, the cache type
     * is stored in the client SSL context.
     */
    TLScontext = tls_alloc_sess_context(log_mask, props->namaddr);
    TLScontext->cache_type = app_ctx->cache_type;

    TLScontext->serverid = myserverid;
    TLScontext->stream = props->stream;
    TLScontext->mdalg = props->mdalg;

    /* Alias DANE digest info from props */
    TLScontext->dane = props->dane;

    if ((TLScontext->con = SSL_new(app_ctx->ssl_ctx)) == NULL) {
	msg_warn("Could not allocate 'TLScontext->con' with SSL_new()");
	tls_print_errors();
	tls_free_context(TLScontext);
	return (0);
    }
    if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
	msg_warn("Could not set application data for 'TLScontext->con'");
	tls_print_errors();
	tls_free_context(TLScontext);
	return (0);
    }

    /*
     * Apply session protocol restrictions.
     */
    if (protomask != 0)
	SSL_set_options(TLScontext->con, TLS_SSL_OP_PROTOMASK(protomask));

    /*
     * XXX To avoid memory leaks we must always call SSL_SESSION_free() after
     * calling SSL_set_session(), regardless of whether or not the session
     * will be reused.
     */
    if (TLScontext->cache_type) {
	session = load_clnt_session(TLScontext);
	if (session) {
	    SSL_set_session(TLScontext->con, session);
	    SSL_SESSION_free(session);		/* 200411 */
	}
    }
#ifdef TLSEXT_MAXLEN_host_name
    if (TLS_DANE_BASED(props->tls_level)
	&& strlen(props->host) <= TLSEXT_MAXLEN_host_name) {

	/*
	 * With DANE sessions, send an SNI hint.  We don't care whether the
	 * server reports finding a matching certificate or not, so no
	 * callback is required to process the server response.  Our use of
	 * SNI is limited to giving servers that are (mis)configured to use
	 * SNI the best opportunity to find the certificate they promised via
	 * the associated TLSA RRs.  (Generally, server administrators should
	 * avoid SNI, and there are no plans to support SNI in the Postfix
	 * SMTP server).
	 * 
	 * Since the hostname is DNSSEC-validated, it must be a DNS FQDN and
	 * thererefore valid for use with SNI.  Failure to set a valid SNI
	 * hostname is a memory allocation error, and thus transient.  Since
	 * we must not cache the session if we failed to send the SNI name,
	 * we have little choice but to abort.
	 */
	if (!SSL_set_tlsext_host_name(TLScontext->con, props->host)) {
	    msg_warn("%s: error setting SNI hostname to: %s", props->namaddr,
		     props->host);
	    tls_free_context(TLScontext);
	    return (0);
	}
	if (log_mask & TLS_LOG_DEBUG)
	    msg_info("%s: SNI hostname: %s", props->namaddr, props->host);
    }
#endif

    /*
     * Before really starting anything, try to seed the PRNG a little bit
     * more.
     */
    tls_int_seed();
    (void) tls_ext_seed(var_tls_daemon_rand_bytes);

    /*
     * Initialize the SSL connection to connect state. This should not be
     * necessary anymore since 0.9.3, but the call is still in the library
     * and maintaining compatibility never hurts.
     */
    SSL_set_connect_state(TLScontext->con);

    /*
     * Connect the SSL connection with the network socket.
     */
    if (SSL_set_fd(TLScontext->con, vstream_fileno(props->stream)) != 1) {
	msg_info("SSL_set_fd error to %s", props->namaddr);
	tls_print_errors();
	uncache_session(app_ctx->ssl_ctx, TLScontext);
	tls_free_context(TLScontext);
	return (0);
    }

    /*
     * Turn on non-blocking I/O so that we can enforce timeouts on network
     * I/O.
     */
    non_blocking(vstream_fileno(props->stream), NON_BLOCKING);

    /*
     * If the debug level selected is high enough, all of the data is dumped:
     * TLS_LOG_TLSPKTS will dump the SSL negotiation, TLS_LOG_ALLPKTS will
     * dump everything.
     * 
     * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
     * Well there is a BIO below the SSL routines that is automatically
     * created for us, so we can use it for debugging purposes.
     */
    if (log_mask & TLS_LOG_TLSPKTS)
	BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);

    tls_dane_set_callback(app_ctx->ssl_ctx, TLScontext);

    /*
     * Start TLS negotiations. This process is a black box that invokes our
     * call-backs for certificate verification.
     * 
     * Error handling: If the SSL handhake fails, we print out an error message
     * and remove all TLS state concerning this session.
     */
    sts = tls_bio_connect(vstream_fileno(props->stream), props->timeout,
			  TLScontext);
    if (sts <= 0) {
	if (ERR_peek_error() != 0) {
	    msg_info("SSL_connect error to %s: %d", props->namaddr, sts);
	    tls_print_errors();
	} else if (errno != 0) {
	    msg_info("SSL_connect error to %s: %m", props->namaddr);
	} else {
	    msg_info("SSL_connect error to %s: lost connection",
		     props->namaddr);
	}
	uncache_session(app_ctx->ssl_ctx, TLScontext);
	tls_free_context(TLScontext);
	return (0);
    }
    /* Turn off packet dump if only dumping the handshake */
    if ((log_mask & TLS_LOG_ALLPKTS) == 0)
	BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);

    /*
     * The caller may want to know if this session was reused or if a new
     * session was negotiated.
     */
    TLScontext->session_reused = SSL_session_reused(TLScontext->con);
    if ((log_mask & TLS_LOG_CACHE) && TLScontext->session_reused)
	msg_info("%s: Reusing old session", TLScontext->namaddr);

    /*
     * Do peername verification if requested and extract useful information
     * from the certificate for later use.
     */
    if ((peercert = SSL_get_peer_certificate(TLScontext->con)) != 0) {
	TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT;

	/*
	 * Peer name or fingerprint verification as requested.
	 * Unconditionally set peer_CN, issuer_CN and peer_cert_fprint. Check
	 * fingerprint first, and avoid logging verified as untrusted in the
	 * call to verify_extract_name().
	 */
	verify_extract_print(TLScontext, peercert, props);
	verify_extract_name(TLScontext, peercert, props);

	if (TLScontext->log_mask &
	    (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
	    msg_info("%s: subject_CN=%s, issuer_CN=%s, "
		     "fingerprint=%s, pkey_fingerprint=%s", props->namaddr,
		     TLScontext->peer_CN, TLScontext->issuer_CN,
		     TLScontext->peer_cert_fprint,
		     TLScontext->peer_pkey_fprint);
	X509_free(peercert);
    } else {
	TLScontext->issuer_CN = mystrdup("");
	TLScontext->peer_CN = mystrdup("");
	TLScontext->peer_cert_fprint = mystrdup("");
	TLScontext->peer_pkey_fprint = mystrdup("");
    }

    /*
     * Finally, collect information about protocol and cipher for logging
     */
    TLScontext->protocol = SSL_get_version(TLScontext->con);
    cipher = SSL_get_current_cipher(TLScontext->con);
    TLScontext->cipher_name = SSL_CIPHER_get_name(cipher);
    TLScontext->cipher_usebits = SSL_CIPHER_get_bits(cipher,
					     &(TLScontext->cipher_algbits));

    /*
     * The TLS engine is active. Switch to the tls_timed_read/write()
     * functions and make the TLScontext available to those functions.
     */
    tls_stream_start(props->stream, TLScontext);

    /*
     * All the key facts in a single log entry.
     */
    if (log_mask & TLS_LOG_SUMMARY)
	msg_info("%s TLS connection established to %s: %s with cipher %s "
		 "(%d/%d bits)",
		 !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" :
		 TLS_CERT_IS_MATCHED(TLScontext) ? "Verified" :
		 TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
	      props->namaddr, TLScontext->protocol, TLScontext->cipher_name,
		 TLScontext->cipher_usebits, TLScontext->cipher_algbits);

    tls_int_seed();

    return (TLScontext);
}
Exemple #29
0
/****************************** transfer data */
static int transfer(CLI *c) {
    int num, err;
    int check_SSL_pending;
    enum {CL_OPEN, CL_INIT, CL_RETRY, CL_CLOSED} ssl_closing=CL_OPEN;
    int watchdog=0; /* a counter to detect an infinite loop */

    c->sock_ptr=c->ssl_ptr=0;
    sock_rd=sock_wr=ssl_rd=ssl_wr=1;
    c->sock_bytes=c->ssl_bytes=0;

    do { /* main loop */
        /* set flag to try and read any buffered SSL data
         * if we made room in the buffer by writing to the socket */
        check_SSL_pending=0;

        /****************************** setup c->fds structure */
        s_poll_zero(&c->fds); /* Initialize the structure */
        if(sock_rd && c->sock_ptr<BUFFSIZE) /* socket input buffer not full*/
            s_poll_add(&c->fds, c->sock_rfd->fd, 1, 0);
        if((ssl_rd && c->ssl_ptr<BUFFSIZE) || /* SSL input buffer not full */
                ((c->sock_ptr || ssl_closing==CL_RETRY) && want_rd))
                /* want to SSL_write or SSL_shutdown but read from the
                 * underlying socket needed for the SSL protocol */
            s_poll_add(&c->fds, c->ssl_rfd->fd, 1, 0);
        if(c->ssl_ptr) /* SSL input buffer not empty */
            s_poll_add(&c->fds, c->sock_wfd->fd, 0, 1);
        if(c->sock_ptr || /* socket input buffer not empty */
                ssl_closing==CL_INIT /* need to send close_notify */ ||
                ((c->ssl_ptr<BUFFSIZE || ssl_closing==CL_RETRY) && want_wr))
                /* want to SSL_read or SSL_shutdown but write to the
                 * underlying socket needed for the SSL protocol */
            s_poll_add(&c->fds, c->ssl_wfd->fd, 0, 1);

        /****************************** wait for an event */
        err=s_poll_wait(&c->fds, (sock_rd && ssl_rd) /* both peers open */ ||
            c->ssl_ptr /* data buffered to write to socket */ ||
            c->sock_ptr /* data buffered to write to SSL */ ?
            c->opt->timeout_idle : c->opt->timeout_close);
        switch(err) {
        case -1:
            sockerror("transfer: s_poll_wait");
            return -1;
        case 0: /* timeout */
            if((sock_rd && ssl_rd) || c->ssl_ptr || c->sock_ptr) {
                s_log(LOG_INFO, "s_poll_wait timeout: connection reset");
                return -1;
            } else { /* already closing connection */
                s_log(LOG_INFO, "s_poll_wait timeout: connection close");
                return 0; /* OK */
            }
        }
        if(!(sock_can_rd || sock_can_wr || ssl_can_rd || ssl_can_wr)) {
            s_log(LOG_ERR, "INTERNAL ERROR: "
                "s_poll_wait returned %d, but no descriptor is ready", err);
            return -1;
        }

        /****************************** send SSL close_notify message */
        if(ssl_closing==CL_INIT || (ssl_closing==CL_RETRY &&
                ((want_rd && ssl_can_rd) || (want_wr && ssl_can_wr)))) {
            switch(SSL_shutdown(c->ssl)) { /* Send close_notify */
            case 1: /* the shutdown was successfully completed */
                s_log(LOG_INFO, "SSL_shutdown successfully sent close_notify");
                ssl_closing=CL_CLOSED; /* done! */
                break;
            case 0: /* the shutdown is not yet finished */
                s_log(LOG_DEBUG, "SSL_shutdown retrying");
                ssl_closing=CL_RETRY; /* retry next time */
                break;
            case -1: /* a fatal error occurred */
                sslerror("SSL_shutdown");
                return -1;
            }
        }

        /****************************** write to socket */
        if(sock_wr && sock_can_wr) {


		/* for stunnel to tell web server the remote ip address */
		add_remote_ip_to_header(c);


            num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr);
            switch(num) {
            case -1: /* error */
                if(parse_socket_error("writesocket"))
                    return -1;
                break;
            case 0:
                s_log(LOG_DEBUG, "No data written to the socket: retrying");
                break;
            default:
                memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num);
                if(c->ssl_ptr==BUFFSIZE) /* buffer was previously full */
                    check_SSL_pending=1; /* check for data buffered by SSL */
                c->ssl_ptr-=num;
                c->sock_bytes+=num;
                watchdog=0; /* reset watchdog */
            }
        }

        /****************************** write to SSL */
        if(ssl_wr && c->sock_ptr && ( /* output buffer not empty */
                ssl_can_wr || (want_rd && ssl_can_rd)
                /* SSL_write wants to read from the underlying descriptor */
                )) {
            num=SSL_write(c->ssl, c->sock_buff, c->sock_ptr);
            switch(err=SSL_get_error(c->ssl, num)) {
            case SSL_ERROR_NONE:
                memmove(c->sock_buff, c->sock_buff+num, c->sock_ptr-num);
                c->sock_ptr-=num;
                c->ssl_bytes+=num;
                watchdog=0; /* reset watchdog */
                break;
            case SSL_ERROR_WANT_WRITE:
                s_log(LOG_DEBUG, "SSL_write returned WANT_WRITE: retrying");
                break;
            case SSL_ERROR_WANT_READ:
                s_log(LOG_DEBUG, "SSL_write returned WANT_READ: retrying");
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                s_log(LOG_DEBUG,
                    "SSL_write returned WANT_X509_LOOKUP: retrying");
                break;
            case SSL_ERROR_SYSCALL: /* really an error */
                if(num && parse_socket_error("SSL_write"))
                    return -1;
                break;
            case SSL_ERROR_ZERO_RETURN: /* close_notify received */
                s_log(LOG_DEBUG, "SSL closed on SSL_write");
                ssl_rd=0;
                break;
            case SSL_ERROR_SSL:
                sslerror("SSL_write");
                return -1;
            default:
                s_log(LOG_ERR, "SSL_write/SSL_get_error returned %d", err);
                return -1;
            }
        }

        /****************************** read from socket */
        if(sock_rd && sock_can_rd) {
            num=readsocket(c->sock_rfd->fd,
                c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr);
            switch(num) {
            case -1:
                if(parse_socket_error("readsocket"))
                    return -1;
                break;
            case 0: /* close */
                s_log(LOG_DEBUG, "Socket closed on read");
                sock_rd=0;
                break;
            default:
                c->sock_ptr+=num;
                watchdog=0; /* reset watchdog */
            }
        }

        /****************************** read from SSL */
        if(ssl_rd && c->ssl_ptr<BUFFSIZE  && ( /* input buffer not full */
                ssl_can_rd || (want_wr && ssl_can_wr) ||
                /* SSL_read wants to write to the underlying descriptor */
                (check_SSL_pending && SSL_pending(c->ssl))
                /* write made space from full buffer */
                )) {
            num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr);
            switch(err=SSL_get_error(c->ssl, num)) {
            case SSL_ERROR_NONE:
                c->ssl_ptr+=num;
                watchdog=0; /* reset watchdog */
                break;
            case SSL_ERROR_WANT_WRITE:
                s_log(LOG_DEBUG, "SSL_read returned WANT_WRITE: retrying");
                break;
            case SSL_ERROR_WANT_READ:
                s_log(LOG_DEBUG, "SSL_read returned WANT_READ: retrying");
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                s_log(LOG_DEBUG,
                    "SSL_read returned WANT_X509_LOOKUP: retrying");
                break;
            case SSL_ERROR_SYSCALL:
                if(!num) { /* EOF */
                    if(c->sock_ptr) {
                        s_log(LOG_ERR,
                            "SSL socket closed with %d byte(s) in buffer",
                            c->sock_ptr);
                        return -1; /* reset the socket */
                    }
                    s_log(LOG_DEBUG, "SSL socket closed on SSL_read");
                    ssl_rd=ssl_wr=0; /* buggy or SSLv2 peer: no close_notify */
                    ssl_closing=CL_CLOSED; /* don't try to send it back */
                } else if(parse_socket_error("SSL_read"))
                    return -1;
                break;
            case SSL_ERROR_ZERO_RETURN: /* close_notify received */
                s_log(LOG_DEBUG, "SSL closed on SSL_read");
                ssl_rd=0;
                break;
            case SSL_ERROR_SSL:
                sslerror("SSL_read");
                return -1;
            default:
                s_log(LOG_ERR, "SSL_read/SSL_get_error returned %d", err);
                return -1;
            }
        }

        /****************************** check write shutdown conditions */
        if(sock_wr && !ssl_rd && !c->ssl_ptr) {
            s_log(LOG_DEBUG, "Socket write shutdown");
            sock_wr=0; /* no further write allowed */
            shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */
        }
        if(ssl_wr && (!sock_rd || SSL_get_shutdown(c->ssl)) && !c->sock_ptr) {
            s_log(LOG_DEBUG, "SSL write shutdown");
            ssl_wr=0; /* no further write allowed */
            if(strcmp(SSL_get_version(c->ssl), "SSLv2")) { /* SSLv3, TLSv1 */
                ssl_closing=CL_INIT; /* initiate close_notify */
            } else { /* no alerts in SSLv2 including close_notify alert */
                shutdown(c->sock_rfd->fd, SHUT_RD); /* notify the kernel */
                shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */
                SSL_set_shutdown(c->ssl, /* notify the OpenSSL library */
                    SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
                ssl_rd=0; /* no further read allowed */
                ssl_closing=CL_CLOSED; /* closed */
            }
        }
        if(ssl_closing==CL_RETRY) { /* SSL shutdown */
            if(!want_rd && !want_wr) { /* close_notify alert was received */
                s_log(LOG_DEBUG, "SSL doesn't need to read or write");
                ssl_closing=CL_CLOSED;
            }
            if(watchdog>5) {
                s_log(LOG_NOTICE, "Too many retries on SSL shutdown");
                ssl_closing=CL_CLOSED;
            }
        }

        /****************************** check watchdog */
        if(++watchdog>100) { /* loop executes without transferring any data */
            s_log(LOG_ERR,
                "transfer() loop executes not transferring any data");
            s_log(LOG_ERR,
                "please report the problem to [email protected]");
            s_log(LOG_ERR, "socket open: rd=%s wr=%s, ssl open: rd=%s wr=%s",
                sock_rd ? "yes" : "no", sock_wr ? "yes" : "no",
                ssl_rd ? "yes" : "no", ssl_wr ? "yes" : "no");
            s_log(LOG_ERR, "socket ready: rd=%s wr=%s, ssl ready: rd=%s wr=%s",
                sock_can_rd ? "yes" : "no", sock_can_wr ? "yes" : "no",
                ssl_can_rd ? "yes" : "no", ssl_can_wr ? "yes" : "no");
            s_log(LOG_ERR, "ssl want: rd=%s wr=%s",
                want_rd ? "yes" : "no", want_wr ? "yes" : "no");
            s_log(LOG_ERR, "socket input buffer: %d byte(s), "
                "ssl input buffer: %d byte(s)", c->sock_ptr, c->ssl_ptr);
            s_log(LOG_ERR, "check_SSL_pending=%d, ssl_closing=%d",
                check_SSL_pending, ssl_closing);
            return -1;
        }

    } while(sock_wr || ssl_closing!=CL_CLOSED);

    return 0; /* OK */
}
Exemple #30
0
extern "C" const char* CryptoNative_SslGetVersion(SSL* ssl)
{
    return SSL_get_version(ssl);
}