Example #1
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;
}
Example #2
0
int tlsops_cipher(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	str cipher;
	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_cipher\n");
		goto err;
	}
	ssl = get_ssl(c);
	if (!ssl) goto err;

	cipher.s = (char*)SSL_CIPHER_get_name(SSL_get_current_cipher(ssl));
	cipher.len = cipher.s ? strlen(cipher.s) : 0;
	if (cipher.len >= 1024) {
		LM_ERR("cipher name too long\n");
		goto err;
	}
	memcpy(buf, cipher.s, cipher.len);
	res->rs.s = buf;
	res->rs.len = cipher.len;
	res->flags = PV_VAL_STR;
	tcpconn_put(c);

	return 0;
err:
	if (c) tcpconn_put(c);
	return pv_get_null(msg, param, res);
}
Example #3
0
static int get_cipher(str* res, sip_msg_t* msg) 
{
	str cipher;
	static char buf[1024];

	struct tcp_connection* c;
	SSL* ssl;

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

	cipher.s = (char*)SSL_CIPHER_get_name(SSL_get_current_cipher(ssl));
	cipher.len = cipher.s ? strlen(cipher.s) : 0;
	if (cipher.len >= 1024) {
		ERR("Cipher name too long\n");
		goto err;
	}
	memcpy(buf, cipher.s, cipher.len);
	res->s = buf;
	res->len = cipher.len;
	tcpconn_put(c);
	return 0;

 err:
	if (c) tcpconn_put(c);
	return -1;
}
Example #4
0
static int get_bits(str* res, int* i, sip_msg_t* msg) 
{
	str bits;
	int b;
	static char buf[1024];

	struct tcp_connection* c;
	SSL* ssl;

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

	b = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), 0);
	bits.s = int2str(b, &bits.len);
	if (bits.len >= 1024) {
		ERR("Bits string too long\n");
		goto err;
	}
	memcpy(buf, bits.s, bits.len);
	res->s = buf;
	res->len = bits.len;
	if (i) *i = b;
	tcpconn_put(c);
	return 0;

 err:
	if (c) tcpconn_put(c);
	return -1;
}
Example #5
0
int 
_write(SSL_CTX *ctx, int sockfd) {
  int res = 0;
#ifdef WITH_DTLS
  SSL *ssl;
  int err;

  ssl = get_ssl(ctx, sockfd, NULL, 1);
  if (!ssl) {
    fprintf(stderr, "no SSL object for writing");
    return 0;
  }
  res = SSL_write(ssl, NULL, 0);
  if (res < 0) {
    /*
    if (SSL_want_write(ssl))
      return 0;
    */
    /* FIXME: check SSL_want_read(ssl) */

    err = SSL_get_error(ssl,res);
    fprintf(stderr,"SSL_write returned %d (%s)\n", err, ERR_error_string(err, NULL));
  } else {
    printf("SSL_write successful\n");
  }
#else
#endif
  
  return res;
}
Example #6
0
static int get_cert(X509** cert, struct tcp_connection** c, struct sip_msg* msg, int my)
{
	SSL* ssl;

	*cert = 0;
	*c = get_cur_connection(msg);
	if (!(*c)) {
		INFO("TLS connection not found\n");
		return -1;
	}
	ssl = get_ssl(*c);
	if (!ssl) goto err;
	*cert = my ? SSL_get_certificate(ssl) : SSL_get_peer_certificate(ssl);
	if (!*cert) {
		if (my) {
			ERR("Unable to retrieve my TLS certificate from SSL structure\n");
		} else {
			ERR("Unable to retrieve peer TLS certificate from SSL structure\n");
		}
		goto err;
	}
	
	return 0;
	
 err:
	tcpconn_put(*c);
	return -1;
}
Example #7
0
int tlsops_desc(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	static char buf[128];

	struct tcp_connection* c;
	SSL* ssl;

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

	buf[0] = '\0';
	SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, 128);
	res->rs.s = buf;
	res->rs.len = strlen(buf);
	res->flags = PV_VAL_STR;

	tcpconn_put(c);

	return 0;
err:
	if (c) tcpconn_put(c);
	return pv_get_null(msg, param, res);
}
Example #8
0
static int get_desc(str* res, sip_msg_t* msg)
{
	static char buf[128];

	struct tcp_connection* c;
	SSL* ssl;

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

	buf[0] = '\0';
	SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, 128);
	res->s = buf;
	res->len = strlen(buf);
	tcpconn_put(c);
	return 0;

 err:
	if (c) tcpconn_put(c);
	return -1;	
}
Example #9
0
static int
ssl_session_init(struct vsf_session* p_sess)
{
  SSL* p_ssl = get_ssl(p_sess, VSFTP_COMMAND_FD);
  if (p_ssl == NULL)
  {
    return 0;
  }
  p_sess->p_control_ssl = p_ssl;
  return 1;
}
Example #10
0
int
ssl_accept(struct vsf_session* p_sess, int fd)
{
  SSL* p_ssl = get_ssl(p_sess, fd);
  if (p_ssl == NULL)
  {
    return 0;
  }
  p_sess->p_data_ssl = p_ssl;
  return 1;
}
Example #11
0
int
ssl_handshake(struct vsf_session* p_sess, int fd)
{
  /* SECURITY: data SSL connections don't have any auth on them as part of the
   * protocol. If a client sends an unfortunately optional client cert then
   * we can check for a match between the control and data connections.
   */
  SSL* p_ssl;
  int reused;
  if (p_sess->p_data_ssl != NULL)
  {
    die("p_data_ssl should be NULL.");
  }
  /* Initiate the SSL connection by either calling accept or connect */
  p_ssl = get_ssl(p_sess, fd);
  if (p_ssl == NULL)
  {
    return 0;
  }
  p_sess->p_data_ssl = p_ssl;
  setup_bio_callbacks(p_ssl);
  reused = SSL_session_reused(p_ssl);
  if (tunable_require_ssl_reuse && !reused)
  {
    str_alloc_text(&debug_str, "No SSL session reuse on data channel.");
    vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
    ssl_data_close(p_sess);
    return 0;
  }
  if (str_getlen(&p_sess->control_cert_digest) > 0)
  {
    static struct mystr data_cert_digest;
    if (!ssl_cert_digest(p_ssl, p_sess, &data_cert_digest))
    {
      str_alloc_text(&debug_str, "Missing cert on data channel.");
      vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
      ssl_data_close(p_sess);
      return 0;
    }
    if (str_strcmp(&p_sess->control_cert_digest, &data_cert_digest))
    {
      str_alloc_text(&debug_str, "DIFFERENT cert on data channel.");
      vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
      ssl_data_close(p_sess);
      return 0;
    }
    if (tunable_debug_ssl)
    {
      str_alloc_text(&debug_str, "Matching cert on data channel.");
      vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str);
    }
  }
  return 1;
}
Example #12
0
static int
ssl_session_init(struct vsf_session* p_sess)
{
  SSL* p_ssl = get_ssl(p_sess, VSFTP_COMMAND_FD);
  if (p_ssl == NULL)
  {
    return 0;
  }
  p_sess->p_control_ssl = p_ssl;
  (void) ssl_cert_digest(p_ssl, p_sess, &p_sess->control_cert_digest);
  setup_bio_callbacks(p_ssl);
  return 1;
}
Example #13
0
static int get_tlsext_sn(str* res, sip_msg_t* msg)
{
	static char buf[1024];
	struct tcp_connection* c;
	str server_name;	
	SSL* ssl;

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

	buf[0] = '\0';

	server_name.s = (char*)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
	if (server_name.s) {
		server_name.len = strlen(server_name.s);
		DBG("received server_name (TLS extension): '%.*s'\n", 
			STR_FMT(&server_name));
	} else {
		DBG("SSL_get_servername returned NULL\n");
		goto error;
	}
	
	/* copy server_name into the buffer. If the buffer is too small copy only
	 * the last bytes as these are the more important ones and prefix with
	 * '+' */
	if (server_name.len > sizeof(buf)) {
		ERR("server_name to big for buffer\n");
		buf[0] = '+';
		memcpy(buf + 1, server_name.s + 1 + server_name.len - sizeof(buf), 
			   sizeof(buf) - 1);
		res->len = sizeof(buf);
	} else {
		memcpy(buf, server_name.s, server_name.len);
		res->len = server_name.len;
	}
	res->s = buf;
	
	tcpconn_put(c);
	return 0;
	
error:
	if (c) tcpconn_put(c);
	return -1;
}
Example #14
0
/*
 * Check whether peer certificate exists and verify the result
 * of certificate verification
 */
int tlsops_check_cert(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	static str succ = str_init("1");
	static str fail = str_init("0");

	int err;
	struct tcp_connection* c;
	SSL* ssl;
	X509* cert = 0;

	switch (param->pvn.u.isname.name.n) {
	case CERT_VERIFIED:   err = X509_V_OK;                              break;
	case CERT_REVOKED:    err = X509_V_ERR_CERT_REVOKED;                break;
	case CERT_EXPIRED:    err = X509_V_ERR_CERT_HAS_EXPIRED;            break;
	case CERT_SELFSIGNED: err = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; break;
	default:
		LM_CRIT("unexpected parameter value \"%d\"\n",
				param->pvn.u.isname.name.n);
		return pv_get_null(msg, param, res);
	}   

	c = get_cur_connection(msg);
	if (!c) return -1;

	ssl = get_ssl(c);
	if (!ssl) goto err;

	if ((cert = SSL_get_peer_certificate(ssl)) && SSL_get_verify_result(ssl) == err) {
		res->rs.s = succ.s;
		res->rs.len = succ.len;
		res->ri   = 1;
	} else {
		res->rs.s = fail.s;
		res->rs.len = fail.len;
		res->ri   = 0;
	}
	res->flags = PV_VAL_STR | PV_VAL_INT;

	if (cert) X509_free(cert);
	tcpconn_put(c);

	return 0;
err:
	if (cert) X509_free(cert);
	if (c) tcpconn_put(c);
	return pv_get_null(msg, param, res);
}
   DLLLOCAL int set_url_unlocked(const char* str, ExceptionSink* xsink) {
      QoreURL url(str);

      if (!url.isValid()) {
	 xsink->raiseException("HTTP-CLIENT-URL-ERROR", "URL '%s' cannot be parsed", str);
	 return -1;
      }
      
      bool port_set = false;
      if (connection.set_url(url, port_set, xsink))
	 return -1;

      const QoreString *tmp = url.getProtocol();
      if (tmp) {
	 prot_map_t::const_iterator i = prot_map.find(tmp->getBuffer());
	 if (i == prot_map.end()) {
	    xsink->raiseException("HTTP-CLIENT-UNKNOWN-PROTOCOL", "protocol '%s' is not supported.", tmp->getBuffer());
	    return -1;
	 }

	 // set port only if it wasn't overridden in the URL
	 if (!port_set && !connection.is_unix)
	    connection.port = get_port(i->second);
	 
	 // set SSL setting from protocol default
	 connection.ssl = get_ssl(i->second);
      }
      else {
	 connection.ssl = false;
	 if (!port_set)
	    connection.port = default_port;
      }

      if (!proxy_connection.has_url())
	 setSocketPath();

      return 0;
   }
   DLLLOCAL int set_proxy_url_unlocked(const char* pstr, ExceptionSink* xsink) { 
      QoreURL url(pstr);

      if (!url.isValid()) {
	 xsink->raiseException("HTTP-CLIENT-URL-ERROR", "proxy URL '%s' cannot be parsed", pstr);
	 return -1;
      }

      bool port_set = false;
      if (proxy_connection.set_url(url, port_set, xsink))
	 return -1;

      const QoreString *tmp = url.getProtocol();
      if (tmp) {
	 if (strcasecmp(tmp->getBuffer(), "http") && strcasecmp(tmp->getBuffer(), "https")) {
	    xsink->raiseException("HTTP-CLIENT-PROXY-PROTOCOL-ERROR", "protocol '%s' is not supported for proxies, only 'http' and 'https'", tmp->getBuffer());
	    return -1;
	 }

	 prot_map_t::const_iterator i = prot_map.find(tmp->getBuffer());
	 assert(i != prot_map.end());

	 // set port only if it wasn't overridden in the URL
	 if (!port_set && !proxy_connection.is_unix)
	    proxy_connection.port = get_port(i->second);

	 // set SSL setting from protocol default
	 proxy_connection.ssl = get_ssl(i->second);
      }
      else {
	 proxy_connection.ssl = false;
	 if (!port_set)
	    proxy_connection.port = default_port;
      }

      setSocketPath();
      return 0;
   }
Example #17
0
/*
 * Check whether peer certificate exists and verify the result
 * of certificate verification
 */
static int check_cert(str* res, int* ires, int local, int err, sip_msg_t* msg)
{
	static str succ = STR_STATIC_INIT("1");
	static str fail = STR_STATIC_INIT("0");

	struct tcp_connection* c;
	SSL* ssl;
	X509* cert = 0;

	c = get_cur_connection(msg);
	if (!c) return -1;

	ssl = get_ssl(c);
	if (!ssl) goto error;

	if (local) {
		DBG("Verification of local certificates not supported\n");
		goto error;
	} else {
		if ((cert = SSL_get_peer_certificate(ssl)) && SSL_get_verify_result(ssl) == err) {
			*res = succ;
			if (ires) *ires = 1;
		} else {
			*res = fail;
			if (ires) *ires = 0;
		}
	}

	if (cert) X509_free(cert);
	tcpconn_put(c);
	return 0;

 error:
	if (cert) X509_free(cert);
	if (c) tcpconn_put(c);
	return -1;
}
Example #18
0
static inline int get_cert(X509** cert, struct tcp_connection** c,
												struct sip_msg* msg, int my)
{
	SSL* ssl;

	*cert = 0;
	*c = get_cur_connection(msg);
	if (!(*c)) {
		LM_INFO("TLS connection not found\n");
		return -1;
	}
	ssl = get_ssl(*c);
	if (!ssl) goto err;
	*cert = my ? SSL_get_certificate(ssl) : SSL_get_peer_certificate(ssl);
	if (!*cert) {
		LM_ERR("failed to get certificate from SSL structure\n");
		goto err;
	}

	return 0;
err:
	tcpconn_put(*c);
	return -1;
}
Example #19
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);
}
Example #20
0
int tlsops_bits(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	str bits;
	int b;
	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_bits\n");
		goto err;
	}
	ssl = get_ssl(c);
	if (!ssl) goto err;

	b = SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), 0);
	bits.s = int2str(b, &bits.len);
	if (bits.len >= 1024) {
		LM_ERR("bits string too long\n");
		goto err;
	}
	memcpy(buf, bits.s, bits.len);
	res->rs.s = buf;
	res->rs.len = bits.len;
	res->ri = b;
	res->flags = PV_VAL_STR | PV_VAL_INT;
	tcpconn_put(c);

	return 0;
err:
	if (c) tcpconn_put(c);
	return pv_get_null(msg, param, res);
}
Example #21
0
int 
_read(SSL_CTX *ctx, int sockfd) {
  char buf[2000];
  struct sockaddr_in6 src;
  int len, ifindex, i;
  char addr[INET6_ADDRSTRLEN];
  char port[6];
  socklen_t sz = sizeof(struct sockaddr_in6);
#ifdef WITH_DTLS
  SSL *ssl;
  int err;
#endif

  /* Retrieve remote address and interface index as well as the first
     few bytes of the message to demultiplex protocols. */
  memset(&src, 0, sizeof(struct sockaddr_in6));
  len = check_connect(sockfd, buf, 4, (struct sockaddr *)&src, &ifindex);

  if (len < 0)			/* error */
    return len;

#ifndef NDEBUG
  fprintf(stderr,"received packet");
  
  if (getnameinfo((struct sockaddr *)&src, sizeof(src), 
		  addr, sizeof(addr), port, sizeof(port), 
		  NI_NUMERICHOST | NI_NUMERICSERV) == 0)
    fprintf(stderr," from [%s]:%s", addr, port);
  
  fprintf(stderr," on interface %d\n", ifindex);
#endif

  switch (demux_protocol(buf, len)) {
#ifdef WITH_DTLS
  case DTLS :
    ssl = get_ssl(ctx, sockfd, (struct sockaddr *)&src, ifindex);
    if (!ssl) {
      fprintf(stderr, "cannot create new SSL object\n");
      /*      return recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);*/
      len = recvfrom(sockfd, buf, sizeof(buf), MSG_DONTWAIT,
		     (struct sockaddr *)&src, &sz);
      getnameinfo((struct sockaddr *)&src, sz, 
		  addr, sizeof(addr), port, sizeof(port), 
		  NI_NUMERICHOST | NI_NUMERICSERV);
      printf("discarded %d bytes from [%s]:%s\n", len, addr, port);      
      return len;
    }
    len = SSL_read(ssl, buf, sizeof(buf));
    break;
#endif
  case UNKNOWN:
  default :
    len = recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);
  }

  if (len > 0) {
    printf("here is the data:\n");
    for (i=0; i<len; i++)
      printf("%c",buf[i]);
  } if (len == 0) {		/* session closed? */
#ifdef WITH_DTLS
    if (check_close(ssl) <= 0) {
      fprintf(stderr, "not closed\n");
    }
#endif
  } else {
#ifdef WITH_DTLS
    err = SSL_get_error(ssl,len);
    switch (err) {
    case SSL_ERROR_WANT_READ:
      fprintf(stderr, "SSL_ERROR_WANT_READ\n");
      return 0;
    case SSL_ERROR_WANT_WRITE:
      fprintf(stderr, "SSL_ERROR_WANT_WRITE\n");
      return 0;
    default:
      fprintf(stderr, "read: SSL error %d: %s\n", err,
	      ERR_error_string(err, NULL));
      return 0;
    }
#else
    perror("recv");
#endif
  }

  return len;
}