Пример #1
0
int
tls_handshake(struct tls *ctx)
{
	int rv = -1;

	tls_error_clear(&ctx->error);

	if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
		tls_set_errorx(ctx, "invalid operation for context");
		goto out;
	}

	if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) {
		tls_set_errorx(ctx, "handshake already completed");
		goto out;
	}

	if ((ctx->flags & TLS_CLIENT) != 0)
		rv = tls_handshake_client(ctx);
	else if ((ctx->flags & TLS_SERVER_CONN) != 0)
		rv = tls_handshake_server(ctx);

	if (rv == 0) {
		ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn);
		ctx->ssl_peer_chain = SSL_get_peer_cert_chain(ctx->ssl_conn);
		if (tls_conninfo_populate(ctx) == -1)
			rv = -1;
		if (ctx->ocsp == NULL)
			ctx->ocsp = tls_ocsp_setup_from_peer(ctx);
	}
 out:
	/* Prevent callers from performing incorrect error handling */
	errno = 0;
	return (rv);
}
Пример #2
0
/*
 * call-seq:
 *    ssl.peer_cert_chain => [cert, ...] or nil
 */
static VALUE
ossl_ssl_get_peer_cert_chain(VALUE self)
{
    SSL *ssl;
    STACK_OF(X509) *chain;
    X509 *cert;
    VALUE ary;
    int i, num;

    Data_Get_Struct(self, SSL, ssl);
    if(!ssl){
	rb_warning("SSL session is not started yet.");
	return Qnil;
    }
    chain = SSL_get_peer_cert_chain(ssl);
    if(!chain) return Qnil;
    num = sk_X509_num(chain);
    ary = rb_ary_new2(num);
    for (i = 0; i < num; i++){
	cert = sk_X509_value(chain, i);
	rb_ary_push(ary, ossl_x509_new(cert));
    }

    return ary;
}
Пример #3
0
void describeCertificates(SSL* ssl, bool isServer)
{
  // Resumed sessions don't necessarily have chains (not included in session ticket)
  X509 *cert = SSL_get_peer_certificate(ssl);
  if (cert == NULL) {
    fprintf(stderr,"No peer certificates.\n");
  } else {
    fprintf(stderr,"Peer certificates:\n");
    describeCertificate(0, cert);
    X509_free(cert);
    STACK_OF(X509) *certs = SSL_get_peer_cert_chain(ssl); // We don't have to free this apparently
    // Cached sessions may not have a chain
    if (certs != NULL) {
      // On server, chain doesn't include client certificate
      if (isServer) {
        for (int i = 0; i < sk_X509_num(certs); i++) {
          describeCertificate(i+1, sk_X509_value(certs,i));
        }
      } else {
        for (int i = 1; i < sk_X509_num(certs); i++) {
          describeCertificate(i, sk_X509_value(certs,i));
        }
      }
    }
    long verify_result = SSL_get_verify_result(ssl);
    if (verify_result == X509_V_OK) {
      fprintf(stderr,"Certificate OK\n");
    } else {
      // See 'man verify(1SSL)' for meanings of the codes
      fprintf(stderr,"Verification error %ld\n", verify_result);
      ERR_print_errors_fp(stderr);
    }
  }
}
Пример #4
0
/**
 * Return the chain of certificate of the peer.
 */
static int meth_getpeerchain(lua_State *L)
{
  int i;
  int idx = 1;
  int n_certs;
  X509 *cert;
  STACK_OF(X509) *certs;
  p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
  if (ssl->state != LSEC_STATE_CONNECTED) {
    lua_pushnil(L);
    lua_pushstring(L, "closed");
    return 2;
  }
  lua_newtable(L);
  if (ssl->ssl->server) {
    lsec_pushx509(L, SSL_get_peer_certificate(ssl->ssl));
    lua_rawseti(L, -2, idx++);
  }
  certs = SSL_get_peer_cert_chain(ssl->ssl);
  n_certs = sk_X509_num(certs);
  for (i = 0; i < n_certs; i++) {
    cert = sk_X509_value(certs, i);
    /* Increment the reference counting of the object. */
    /* See SSL_get_peer_certificate() source code.     */
    CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
    lsec_pushx509(L, cert);
    lua_rawseti(L, -2, idx++);
  }
  return 1;
}
Пример #5
0
static CryptoCert tls_get_certificate(rdpTls* tls, BOOL peer)
{
	CryptoCert cert;
	X509* remote_cert;
	STACK_OF(X509) *chain;

	if (peer)
		remote_cert = SSL_get_peer_certificate(tls->ssl);
	else
		remote_cert = X509_dup(SSL_get_certificate(tls->ssl));

	if (!remote_cert)
	{
		WLog_ERR(TAG, "failed to get the server TLS certificate");
		return NULL;
	}

	cert = malloc(sizeof(*cert));

	if (!cert)
	{
		X509_free(remote_cert);
		return NULL;
	}

	cert->px509 = remote_cert;
	/* Get the peer's chain. If it does not exist, we're setting NULL (clean data either way) */
	chain = SSL_get_peer_cert_chain(tls->ssl);
	cert->px509chain = chain;
	return cert;
}
Пример #6
0
static PyObject *
ssl_Connection_get_peer_cert_chain(ssl_ConnectionObj *self, PyObject *args) {
    STACK_OF(X509) *sk;
    PyObject *chain;
    crypto_X509Obj *cert;
    Py_ssize_t i;

    if (!PyArg_ParseTuple(args, ":get_peer_cert_chain")) {
        return NULL;
    }

    sk = SSL_get_peer_cert_chain(self->ssl);
    if (sk != NULL) {
        chain = PyList_New(sk_X509_num(sk));
        for (i = 0; i < sk_X509_num(sk); i++) {
            cert = new_x509(sk_X509_value(sk, i), 1);
            if (!cert) {
                /* XXX Untested */
                Py_DECREF(chain);
                return NULL;
            }
            CRYPTO_add(&cert->x509->references, 1, CRYPTO_LOCK_X509);
            PyList_SET_ITEM(chain, i, (PyObject *)cert);
        }
        return chain;
    } else {
        Py_INCREF(Py_None);
        return Py_None;
    }

}
Пример #7
0
static int ssl_check_certificate (CONNECTION *conn, sslsockdata *data)
{
        int i, preauthrc, chain_len;
        STACK_OF(X509) *chain;
        X509 *cert;

        if ((preauthrc = ssl_check_preauth (data->cert, conn->account.host)) > 0)
                return preauthrc;

        chain = SSL_get_peer_cert_chain (data->ssl);
        chain_len = sk_X509_num (chain);
/* negative preauthrc means the certificate won't be accepted without
 * manual override. */
        if (preauthrc < 0 || !chain || (chain_len <= 1))
                return interactive_check_cert (data->cert, 0, 0);

/* check the chain from root to peer. */
        for (i = chain_len-1; i >= 0; i--) {
                cert = sk_X509_value (chain, i);

/* if the certificate validates or is manually accepted, then add it to
 * the trusted set and recheck the peer certificate */
                if (ssl_check_preauth (cert, NULL)
                || interactive_check_cert (cert, i, chain_len)) {
                        ssl_cache_trusted_cert (cert);
                        if (ssl_check_preauth (data->cert, conn->account.host))
                                return 1;
                }
        }

        return 0;
}
Пример #8
0
/*
 *	Returns: 	0 if successfully matching certificate to TLSA record bytes
 *				-1 if there was no match
 */
int ca_constraint(const SSL *con, const X509 *tlsa_cert, int usage) {
	STACK_OF(X509) *cert_chain = NULL;
	cert_chain = SSL_get_peer_cert_chain(con);
	BIO_printf(b_err, "DANE ca_constraint() chain of %d length\n", 
		sk_X509_num(cert_chain));
	int ret_val;
	ret_val = 0;
	
	if (cert_chain != NULL) {
		int i;
		for (i = 0; i < sk_X509_num(cert_chain); i++) {			
			BIO_printf(b_err, "DANE ca_constraint() cert %d of %d.\n",
				i, sk_X509_num(cert_chain));
			/*
			BIO_printf(b_err, "DANE CXN Certificate\n");
			PEM_write_bio_X509(b_err, sk_X509_value(cert_chain, i));
			BIO_printf(b_err, "DANE TLSA Certificate\n");
			PEM_write_bio_X509(b_err, tlsa_cert);
			*/
			if (X509_cmp(tlsa_cert, sk_X509_value(cert_chain, i)) < 0) {
				ret_val = -1;
				BIO_printf(b_err, "DANE ca_constraint() certificates didn't match\n");
			} else {
				BIO_printf(b_err, "DANE ca_constraint() certificates matches\n");
				if (usage == 0)
					return 0;
				
				/*	For this to be a trust anchor, the following characteristics applies:
				 * 	1. Issuer name is the same as Subject name
				 * 	2. Either or both
				 *	a) the Key Usage field is set to keyCertSign (KU_KEY_CERT_SIGN)
				 *	b) the basicConstraints field has the attribute cA set to True (EXFLAG_CA)
				 */
				X509_NAME *issuer_name, *subject_name;
				issuer_name = X509_get_issuer_name(tlsa_cert);
				subject_name = X509_get_subject_name(tlsa_cert);
				
				if (X509_name_cmp(issuer_name, subject_name) == 0) {
					BIO_printf(b_err, "DANE issuer == subject\n");
					
					if (tlsa_cert->ex_flags & EXFLAG_CA) {
						BIO_printf(b_err, "DANE ca_constraint() EXFLAG_CA set\n");
						return 0;
					}
/*	Left unimplemented since I don't have a CA certificate to work with.*/
					int ext_count, j;
					ext_count = X509_get_ext_count(tlsa_cert);
					BIO_printf(b_err, "DANE ca_constraint() %d certificate extensions\n");

				} else {
					return 0;
				}
			}
		}
	}
	return ret_val;
}
Пример #9
0
static int openssl_ssl_peer(lua_State*L)
{
  SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl");
  X509* x = SSL_get_peer_certificate(s);
  STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s);
  PUSH_OBJECT(x, "openssl.x509");
  if (sk)
  {
    sk = openssl_sk_x509_dup(sk);
    PUSH_OBJECT(sk, "openssl.stack_of_x509");
    return 2;
  }
  return 1;
}
Пример #10
0
		bool SSLSocket::verifyKeyprint(const string& expKP, bool allowUntrusted) noexcept
		{
			if (!ssl)
				return true;
				
			if (expKP.empty() || expKP.find("/") == string::npos)
				return allowUntrusted;
				
			verifyData.reset(new CryptoManager::SSLVerifyData(allowUntrusted, expKP));
			SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, verifyData.get());
			
			SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
			X509_STORE* store = X509_STORE_new();
			bool result = false;
			int err = SSL_get_verify_result(ssl);
			if (ssl_ctx && store)
			{
				X509_STORE_CTX* vrfy_ctx = X509_STORE_CTX_new();
				X509* cert = SSL_get_peer_certificate(ssl);
				
				if (vrfy_ctx && cert && X509_STORE_CTX_init(vrfy_ctx, store, cert, SSL_get_peer_cert_chain(ssl)))
				{
					X509_STORE_CTX_set_ex_data(vrfy_ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), ssl);
					X509_STORE_CTX_set_verify_cb(vrfy_ctx, SSL_CTX_get_verify_callback(ssl_ctx));
					
					int verify_result = 0;
					if ((verify_result = X509_verify_cert(vrfy_ctx)) >= 0)
					{
						err = X509_STORE_CTX_get_error(vrfy_ctx);
						
						// Watch out for weird library errors that might not set the context error code
						if (err == X509_V_OK && verify_result <= 0)
							err = X509_V_ERR_UNSPECIFIED;
							
						// This is for people who don't restart their clients and have low expiration time on their cert
						result = (err == X509_V_OK || err == X509_V_ERR_CERT_HAS_EXPIRED) || (allowUntrusted && err != X509_V_ERR_APPLICATION_VERIFICATION);
					}
				}
				
				if (cert) X509_free(cert);
				if (vrfy_ctx) X509_STORE_CTX_free(vrfy_ctx);
				if (store) X509_STORE_free(store);
			}
			
			// KeyPrint is a strong indicator of trust
			SSL_set_verify_result(ssl, err);
			
			return result;
		}
Пример #11
0
/**
 * Return the nth certificate of the peer's chain.
 */
static int meth_getpeercertificate(lua_State *L)
{
  int n;
  X509 *cert;
  STACK_OF(X509) *certs;
  p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
  if (ssl->state != LSEC_STATE_CONNECTED) {
    lua_pushnil(L);
    lua_pushstring(L, "closed");
    return 2;
  }
  /* Default to the first cert */ 
  n = luaL_optint(L, 2, 1);                           
  /* This function is 1-based, but OpenSSL is 0-based */
  --n;
  if (n < 0) {
    lua_pushnil(L);
    lua_pushliteral(L, "invalid certificate index");
    return 2;
  }
  if (n == 0) {
    cert = SSL_get_peer_certificate(ssl->ssl);
    if (cert)
      lsec_pushx509(L, cert);
    else
      lua_pushnil(L);
    return 1;
  }
  /* In a server-context, the stack doesn't contain the peer cert,
   * so adjust accordingly.
   */
  if (ssl->ssl->server)
    --n;
  certs = SSL_get_peer_cert_chain(ssl->ssl);
  if (n >= sk_X509_num(certs)) {
    lua_pushnil(L);
    return 1;
  }
  cert = sk_X509_value(certs, n);
  /* Increment the reference counting of the object. */
  /* See SSL_get_peer_certificate() source code.     */
  CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
  lsec_pushx509(L, cert);
  return 1;
}
Пример #12
0
static void win_new_chain(CLI *c) {
    BIO *bio;
    int i, len;
    X509 *peer=NULL;
    STACK_OF(X509) *sk;
    char *chain;

    if(c->opt->chain) /* already cached */
        return; /* this race condition is safe to ignore */
    bio=BIO_new(BIO_s_mem());
    if(!bio)
        return;
    sk=SSL_get_peer_cert_chain(c->ssl);
    for(i=0; sk && i<sk_X509_num(sk); i++) {
        peer=sk_X509_value(sk, i);
        PEM_write_bio_X509(bio, peer);
    }
    if(!sk || !c->opt->option.client) {
        peer=SSL_get_peer_certificate(c->ssl);
        if(peer) {
            PEM_write_bio_X509(bio, peer);
            X509_free(peer);
        }
    }
    len=BIO_pending(bio);
    if(len<=0) {
        s_log(LOG_INFO, "No peer certificate received");
        BIO_free(bio);
        return;
    }
    chain=str_alloc(len+1);
    len=BIO_read(bio, chain, len);
    if(len<0) {
        s_log(LOG_ERR, "BIO_read failed");
        BIO_free(bio);
        str_free(chain);
        return;
    }
    chain[len]='\0';
    BIO_free(bio);
    str_detach(chain); /* to prevent automatic deallocation of cached value */
    c->opt->chain=chain; /* this race condition is safe to ignore */
    PostMessage(hwnd, WM_NEW_CHAIN, c->opt->section_number, 0);
    s_log(LOG_DEBUG, "Peer certificate was cached (%d bytes)", len);
}
Пример #13
0
Wt::WSslInfo *Request::sslInfo() const
{
#ifdef HTTP_WITH_SSL
  if (!ssl)
    return nullptr;

  X509 *x509 = SSL_get_peer_certificate(ssl);
  
  if (x509) {
    Wt::WSslCertificate clientCert = Wt::Ssl::x509ToWSslCertificate(x509);
    
    X509_free(x509);

    std::vector<Wt::WSslCertificate> clientCertChain;
    STACK_OF(X509) *certChain = SSL_get_peer_cert_chain(ssl);
    if (certChain) {
      for (int i = 0; i < sk_X509_num(certChain); ++i) {
	X509 *x509_i = sk_X509_value(certChain, i);
	clientCertChain.push_back(Wt::Ssl::x509ToWSslCertificate(x509_i));
      }
    }
    
    Wt::ValidationState state = Wt::ValidationState::Invalid;
    std::string info;

    long SSL_state = SSL_get_verify_result(ssl);
    if (SSL_state == X509_V_OK) {
      state = Wt::ValidationState::Valid;
    } else {
      state = Wt::ValidationState::Invalid;
      info = X509_verify_cert_error_string(SSL_state);
    }
    Wt::WValidator::Result clientVerificationResult(state, info);
    
    return new Wt::WSslInfo(clientCert, 
			    clientCertChain, 
			    clientVerificationResult);
  }
#endif
  return nullptr;
}
Пример #14
0
bool SSLSocket::verifyKeyprint(const string& expKP, bool allowUntrusted) noexcept {
	if(!ssl)
		return true;

	if(expKP.empty() || expKP.find("/") == string::npos)
		return allowUntrusted; 

	verifyData.reset(new CryptoManager::SSLVerifyData(allowUntrusted, expKP));
	SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, verifyData.get());

	SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
	X509_STORE* store = SSL_CTX_get_cert_store(ctx);

	bool result = allowUntrusted;
	int err = SSL_get_verify_result(ssl);
	if(ssl_ctx && store) {
		X509_STORE_CTX* vrfy_ctx = X509_STORE_CTX_new();
		X509* cert = SSL_get_peer_certificate(ssl);
		if(vrfy_ctx && cert && X509_STORE_CTX_init(vrfy_ctx, store, cert, SSL_get_peer_cert_chain(ssl))) {
			auto vrfy_cb = SSL_CTX_get_verify_callback(ssl_ctx);

			X509_STORE_CTX_set_ex_data(vrfy_ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), ssl);
			X509_STORE_CTX_set_verify_cb(vrfy_ctx, vrfy_cb);

			if(X509_verify_cert(vrfy_ctx) >= 0) {
				err = X509_STORE_CTX_get_error(vrfy_ctx);
				// This is for people who don't restart their clients and have low expiration time on their cert
				result = (err == X509_V_OK) || (err == X509_V_ERR_CERT_HAS_EXPIRED);
			}
		}

		if(cert) X509_free(cert);
		if(vrfy_ctx) X509_STORE_CTX_free(vrfy_ctx);
	}

	// KeyPrint is a strong indicator of trust (TODO: check that this KeyPrint is mediated by a trusted hub)
	SSL_set_verify_result(ssl, err);

	return result;
}
Пример #15
0
static void sl_ssl_get_cert(void){
  SLssl_Type *ssl;
  SLang_MMT_Type *sslmmt;
  STACK_OF(X509) *cert;
  unsigned char **buf;
  SLang_BString_Type **certout;
  SLang_Array_Type *arr;
  SLindex_Type nelem;
  int len,i;

  if (NULL==(sslmmt=SLang_pop_mmt(SLssl_Type_Id)))
    return;

  ssl=(SLssl_Type *)SLang_object_from_mmt(sslmmt);

  cert=SSL_get_peer_cert_chain((SSL *)ssl->ssl);

  if (cert==NULL)
    return NULL;

  nelem=(SLindex_Type)sk_X509_num(cert);
  // now we have chain of certs, create array of pointers and the
  // array to hold them
  buf = (unsigned char **)malloc(nelem*sizeof(unsigned char *));
  arr = SLang_create_array(SLANG_BSTRING_TYPE,0,NULL,&nelem,1);
  // array data structure is of bstring type
  certout = (SLang_BString_Type **)arr->data;
  
  for (i=0;i<nelem;i++){
    buf[i] = NULL;
    len = i2d_X509(sk_X509_value(cert,i), &(buf[i]));
    certout[i] = SLbstring_create(buf[i],len);
  }
  
  SLang_push_array(arr,1);
  // free the X509 stack
  sk_X509_pop_free(cert,X509_free);
}
Пример #16
0
carray * mailstream_low_ssl_get_certificate_chain(mailstream_low * s)
{
#ifdef USE_SSL
#ifndef USE_GNUTLS
  STACK_OF(X509) * skx;
  struct mailstream_ssl_data * ssl_data;
  carray * result;
  int skpos;
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (!(skx = SSL_get_peer_cert_chain(ssl_data->ssl_conn))) {
    return NULL;
  }
  
  result = carray_new(4);
  for(skpos = 0 ; skpos < sk_num(skx) ; skpos ++) {
    X509 * x = (X509 *) sk_value(skx, skpos);
    unsigned char * p;
    MMAPString * str;
    int length = i2d_X509(x, NULL);
    str = mmap_string_sized_new(length);
    p = (unsigned char *) str->str;
    str->len = length;
    i2d_X509(x, &p);
    carray_add(result, str, NULL);
  }
  
  return result;
#else
  /* TODO: GnuTLS implementation */
  return NULL;
#endif
#else
  return NULL;
#endif
}
Пример #17
0
/* Return a PEM-formatted buffer containing the peer's certificate chain.
 *
 * NULL is returned if there is no certificate chain, or if memory allocation fails.
 */
char *async_ssl__pem_peer_certificate_chain(const SSL *con) {
    STACK_OF(X509) *cert_stack = NULL;
    BIO *bio = NULL;
    char *certs = NULL;
    int i = 0, pending_bytes = 0;

    /* [cert_stack] is not to be freed; [SSL_get_peer_cert_chain] simply returns an
     * internal pointer and no reference count is incremented. */
    if ((cert_stack = SSL_get_peer_cert_chain(con)) == NULL) {
        return NULL;
    }

    if ((bio = BIO_new(BIO_s_mem())) == NULL) {
        return NULL;
    }
    for (i = 0; i < sk_X509_num(cert_stack); i++) {
        if ((PEM_write_bio_X509(bio, sk_X509_value(cert_stack, i))) == 0) {
            goto cleanup;
        }
    }
    pending_bytes = BIO_ctrl_pending(bio);
    if ((certs = malloc((pending_bytes + 1) * sizeof(char))) == NULL) {
        goto cleanup;
    }
    if ((BIO_read(bio, certs, pending_bytes)) < pending_bytes) {
        free(certs);
        goto cleanup;
    }
    certs[pending_bytes] = '\0';

  cleanup:
    BIO_set_close(bio, BIO_CLOSE);
    BIO_free(bio);

    return certs;
}
Пример #18
0
static int verifypeer(const struct tls_info *info, SSL *ssl)
{
	X509 *x=NULL;
	X509_NAME *subj=NULL;
	int nentries, j;
	char domain[256];
	char *p;
	char errmsg[1000];

	if (!info->peer_verify_domain)
		return (1);

	if (info->isserver)
	{
		x=SSL_get_peer_certificate(ssl);

		if (x)
			subj=X509_get_subject_name(x);
	}
	else
	{
		STACK_OF(X509) *peer_cert_chain=SSL_get_peer_cert_chain(ssl);

		if (peer_cert_chain && peer_cert_chain->stack.num > 0)
		{
			X509 *xx=(X509 *)peer_cert_chain->stack.data[0];

			if (xx)
				subj=X509_get_subject_name(xx);
		}
	}

	
	nentries=0;
	if (subj)
		nentries=X509_NAME_entry_count(subj);

	domain[0]=0;
	for (j=0; j<nentries; j++)
	{
		const char *obj_name;
		X509_NAME_ENTRY *e;
		ASN1_OBJECT *o;
		ASN1_STRING *d;

		int dlen;
		unsigned char *ddata;

		e=X509_NAME_get_entry(subj, j);
		if (!e)
			continue;

		o=X509_NAME_ENTRY_get_object(e);
		d=X509_NAME_ENTRY_get_data(e);

		if (!o || !d)
			continue;

		obj_name=OBJ_nid2sn(OBJ_obj2nid(o));

		dlen=ASN1_STRING_length(d);
		ddata=ASN1_STRING_data(d);

		if (strcasecmp(obj_name, "CN") == 0)
		{
			if (dlen >= sizeof(domain)-1)
				dlen=sizeof(domain)-1;

			memcpy(domain, ddata, dlen);
			domain[dlen]=0;
		}
	}

	if (x)
		X509_free(x);
	p=domain;

	if (*p == '*')
	{
		int	pl, l;

		pl=strlen(++p);
		l=strlen(info->peer_verify_domain);

		if (*p == '.' && pl <= l &&
		    strcasecmp(info->peer_verify_domain+l-pl, p) == 0)
			return (1);
	}
	else if (strcasecmp(info->peer_verify_domain, p) == 0)
		return (1);

	strcpy(errmsg, "couriertls: Mismatched SSL certificate: CN=");
	strcat(errmsg, domain);
	strcat(errmsg, " (expected ");
	strncat(errmsg, info->peer_verify_domain, 256);
	strcat(errmsg, ")");
	(*info->tls_err_msg)(errmsg, info->app_data);
	return (0);
}
Пример #19
0
static int
do_ca_cert_bootstrap(struct stream *stream)
{
    struct ssl_stream *sslv = ssl_stream_cast(stream);
    STACK_OF(X509) *chain;
    X509 *cert;
    FILE *file;
    int error;
    int fd;

    chain = SSL_get_peer_cert_chain(sslv->ssl);
    if (!chain || !sk_X509_num(chain)) {
        VLOG_ERR("could not bootstrap CA cert: no certificate presented by "
                 "peer");
        return EPROTO;
    }
    cert = sk_X509_value(chain, sk_X509_num(chain) - 1);

    /* Check that 'cert' is self-signed.  Otherwise it is not a CA
     * certificate and we should not attempt to use it as one. */
    error = X509_check_issued(cert, cert);
    if (error) {
        VLOG_ERR("could not bootstrap CA cert: obtained certificate is "
                 "not self-signed (%s)",
                 X509_verify_cert_error_string(error));
        if (sk_X509_num(chain) < 2) {
            VLOG_ERR("only one certificate was received, so probably the peer "
                     "is not configured to send its CA certificate");
        }
        return EPROTO;
    }

    fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444);
    if (fd < 0) {
        if (errno == EEXIST) {
            VLOG_INFO_RL(&rl, "reading CA cert %s created by another process",
                         ca_cert.file_name);
            stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true);
            return EPROTO;
        } else {
            VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s",
                     ca_cert.file_name, ovs_strerror(errno));
            return errno;
        }
    }

    file = fdopen(fd, "w");
    if (!file) {
        error = errno;
        VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s",
                 ovs_strerror(error));
        unlink(ca_cert.file_name);
        return error;
    }

    if (!PEM_write_X509(file, cert)) {
        VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: "
                 "%s", ca_cert.file_name,
                 ERR_error_string(ERR_get_error(), NULL));
        fclose(file);
        unlink(ca_cert.file_name);
        return EIO;
    }

    if (fclose(file)) {
        error = errno;
        VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s",
                 ca_cert.file_name, ovs_strerror(error));
        unlink(ca_cert.file_name);
        return error;
    }

    VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name);
    log_ca_cert(ca_cert.file_name, cert);
    bootstrap_ca_cert = false;
    ca_cert.read = true;

    /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */
    SSL_CTX_add_client_CA(ctx, cert);

    SSL_CTX_set_cert_store(ctx, X509_STORE_new());
    if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) {
        VLOG_ERR("SSL_CTX_load_verify_locations: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        return EPROTO;
    }
    VLOG_INFO("killing successful connection to retry using CA cert");
    return EPROTO;
}
Пример #20
0
carray * mailstream_low_ssl_get_certificate_chain(mailstream_low * s)
{
#ifdef USE_SSL
  struct mailstream_ssl_data * ssl_data;
  carray * result;
  int skpos;
#ifndef USE_GNUTLS
  STACK_OF(X509) * skx;
  
  ssl_data = (struct mailstream_ssl_data *) s->data;
  if (!(skx = SSL_get_peer_cert_chain(ssl_data->ssl_conn))) {
    return NULL;
  }
  
  result = carray_new(4);
  for(skpos = 0 ; skpos < sk_num((_STACK *) skx) ; skpos ++) {
    X509 * x = (X509 *) sk_value((_STACK *) skx, skpos);
    unsigned char * p;
    MMAPString * str;
    int length = i2d_X509(x, NULL);
    str = mmap_string_sized_new(length);
    p = (unsigned char *) str->str;
    str->len = length;
    i2d_X509(x, &p);
    carray_add(result, str, NULL);
  }
  
  return result;
#else
  gnutls_session session = NULL;
  const gnutls_datum *raw_cert_list;
  unsigned int raw_cert_list_length;

  ssl_data = (struct mailstream_ssl_data *) s->data;

  session = ssl_data->session;
  raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length);

  if (raw_cert_list && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
    result = carray_new(4);
    for(skpos = 0 ; skpos < raw_cert_list_length ; skpos ++) {
      gnutls_x509_crt cert = NULL;
      if (gnutls_x509_crt_init(&cert) >= 0
       && gnutls_x509_crt_import(cert, &raw_cert_list[skpos], GNUTLS_X509_FMT_DER) >= 0) {
         size_t cert_size = 0;
         MMAPString * str = NULL;
         unsigned char * p;

         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &cert_size)
	     == GNUTLS_E_SHORT_MEMORY_BUFFER) {
           str = mmap_string_sized_new(cert_size);
           p = (unsigned char *) str->str;
           str->len = cert_size;
	 }
	 if (str != NULL &&
             gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, p, &cert_size) >= 0) {
           carray_add(result, str, NULL);
	 } else {
	   return NULL;
	 }
         gnutls_x509_crt_deinit(cert);
       }
    }
  }

  return result;

  return NULL;
#endif
#else
  return NULL;
#endif
}
Пример #21
0
void ssl_barf_out(Socket_t S) {
	BIO *ebio;
	char buf[BUFSIZ], *p;
	sock_ssl_t m = XSsl(S);

  if (tb_errorlevel >= TB_NOTICE) {
		STACK      * sk;

    if ((ebio=BIO_new(BIO_s_file())) == NULL) {
      tb_warn("Cannot create new BIO\n");
      ERR_print_errors_fp(stderr);
      return;
    }
    BIO_set_fp(ebio,stderr,BIO_NOCLOSE);
    if ((sk=(STACK *)SSL_get_peer_cert_chain(m->cx)) != NULL) {
			int i;
      BIO_printf(ebio,"---\nCertificate chain\n");
      for (i=0; i<sk_num(sk); i++) {
        X509_NAME_oneline(X509_get_subject_name((X509*)sk_value(sk,i)),buf,BUFSIZ);
        BIO_printf(ebio,"%2d s:%s\n",i,buf);
        X509_NAME_oneline(X509_get_issuer_name((X509 *)sk_value(sk,i)),buf,BUFSIZ);
        BIO_printf(ebio,"   i:%s\n",buf);
      }
    }
    BIO_printf(ebio,"---\n");
    if ((m->peer=SSL_get_peer_certificate(m->cx)) != NULL) {
      BIO_printf(ebio,"Peer certificate\n");
      PEM_write_bio_X509(ebio,m->peer);
      X509_NAME_oneline(X509_get_subject_name(m->peer),buf,BUFSIZ);
      BIO_printf(ebio,"subject=%s\n",buf);
      X509_NAME_oneline(X509_get_issuer_name(m->peer),buf,BUFSIZ);
      BIO_printf(ebio,"issuer=%s\n",buf);
    }
    else
      BIO_printf(ebio,"no peer certificate available\n");
    if (((sk=SSL_get_client_CA_list(m->cx)) != NULL) && (sk_num(sk) > 0)) {
			int i;
      BIO_printf(ebio,"---\nAcceptable peer certificate CA names\n");
      for (i=0; i<sk_num(sk); i++) {
        m->xn=(X509_NAME *)sk_value(sk,i);
        X509_NAME_oneline(m->xn,buf,sizeof(buf));
        BIO_write(ebio,buf,strlen(buf));
        BIO_write(ebio,"\n",1);
      }
    }
    else {
      BIO_printf(ebio,"---\nNo peer certificate CA names sent\n");
    }
    if ((p=SSL_get_shared_ciphers(m->cx,buf,BUFSIZ)) != NULL) {
			int i, j;
      BIO_printf(ebio,"---\nCiphers common between both SSL endpoints:\n");
      j=i=0;
      while (*p) {
        if (*p != ':') {
          BIO_write(ebio,p,1);j++;
        } else {
          BIO_write(ebio,"                ",15-j%25);i++;j=0;
          BIO_write(ebio,((i%3)?" ":"\n"),1);
        }
        p++;
      }
      BIO_write(ebio,"\n",1);
    }
    BIO_printf(ebio,
               "---\nSSL handshake has read %ld bytes and written %ld bytes\n",
               BIO_number_read(SSL_get_rbio(m->cx)),
               BIO_number_written(SSL_get_wbio(m->cx)));
    BIO_printf(ebio,((m->cx->hit)?"---\nReused, ":"---\nNew, "));
    m->sc=SSL_get_current_cipher(m->cx);
    BIO_printf(ebio,"%s, Cipher is %s\n",
               SSL_CIPHER_get_version(m->sc),SSL_CIPHER_get_name(m->sc));
    if(m->peer != NULL) {
      EVP_PKEY *pktmp;
      pktmp = X509_get_pubkey(m->peer);
      BIO_printf(ebio,"Server public key is %d bit\n", EVP_PKEY_bits(pktmp));
      EVP_PKEY_free(pktmp);
    }
    SSL_SESSION_print(ebio,SSL_get_session(m->cx));
    BIO_printf(ebio,"---\n");
    if(m->peer != NULL)
      X509_free(m->peer);
    BIO_free(ebio);
  }
}
Пример #22
0
static int
mta_verify_certificate(struct mta_session *s)
{
	struct ca_vrfy_req_msg	req_ca_vrfy;
	struct iovec		iov[2];
	X509		       *x;
	STACK_OF(X509)	       *xchain;
	int			i;
	const char	       *pkiname;

	x = SSL_get_peer_certificate(s->io.ssl);
	if (x == NULL)
		return 0;
	xchain = SSL_get_peer_cert_chain(s->io.ssl);

	/*
	 * Client provided a certificate and possibly a certificate chain.
	 * SMTP can't verify because it does not have the information that
	 * it needs, instead it will pass the certificate and chain to the
	 * lookup process and wait for a reply.
	 *
	 */

	tree_xset(&wait_ssl_verify, s->id, s);
	s->flags |= MTA_WAIT;

	/* Send the client certificate */
	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
	if (s->relay->pki_name)
		pkiname = s->relay->pki_name;
	else
		pkiname = s->helo;
	if (strlcpy(req_ca_vrfy.pkiname, pkiname, sizeof req_ca_vrfy.pkiname)
	    >= sizeof req_ca_vrfy.pkiname)
		return 0;

	req_ca_vrfy.reqid = s->id;
	req_ca_vrfy.cert_len = i2d_X509(x, &req_ca_vrfy.cert);
	if (xchain)
		req_ca_vrfy.n_chain = sk_X509_num(xchain);
	iov[0].iov_base = &req_ca_vrfy;
	iov[0].iov_len = sizeof(req_ca_vrfy);
	iov[1].iov_base = req_ca_vrfy.cert;
	iov[1].iov_len = req_ca_vrfy.cert_len;
	m_composev(p_lka, IMSG_LKA_SSL_VERIFY_CERT, 0, 0, -1,
	    iov, nitems(iov));
	free(req_ca_vrfy.cert);
	X509_free(x);

	if (xchain) {		
		/* Send the chain, one cert at a time */
		for (i = 0; i < sk_X509_num(xchain); ++i) {
			memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
			req_ca_vrfy.reqid = s->id;
			x = sk_X509_value(xchain, i);
			req_ca_vrfy.cert_len = i2d_X509(x, &req_ca_vrfy.cert);
			iov[0].iov_base = &req_ca_vrfy;
			iov[0].iov_len  = sizeof(req_ca_vrfy);
			iov[1].iov_base = req_ca_vrfy.cert;
			iov[1].iov_len  = req_ca_vrfy.cert_len;
			m_composev(p_lka, IMSG_LKA_SSL_VERIFY_CHAIN, 0, 0, -1,
			    iov, nitems(iov));
			free(req_ca_vrfy.cert);
		}
	}

	/* Tell lookup process that it can start verifying, we're done */
	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
	req_ca_vrfy.reqid = s->id;
	m_compose(p_lka, IMSG_LKA_SSL_VERIFY, 0, 0, -1,
	    &req_ca_vrfy, sizeof req_ca_vrfy);

	return 1;
}
Пример #23
0
static void
print_stuff(BIO * bio, SSL * s, int full)
{
	X509 *peer = NULL;
	char *p;
	static const char *space = "                ";
	char buf[BUFSIZ];
	STACK_OF(X509) * sk;
	STACK_OF(X509_NAME) * sk2;
	const SSL_CIPHER *c;
	X509_NAME *xn;
	int j, i;
	unsigned char *exportedkeymat;

	if (full) {
		int got_a_chain = 0;

		sk = SSL_get_peer_cert_chain(s);
		if (sk != NULL) {
			got_a_chain = 1;	/* we don't have it for SSL2
						 * (yet) */

			BIO_printf(bio, "---\nCertificate chain\n");
			for (i = 0; i < sk_X509_num(sk); i++) {
				X509_NAME_oneline(X509_get_subject_name(
					sk_X509_value(sk, i)), buf, sizeof buf);
				BIO_printf(bio, "%2d s:%s\n", i, buf);
				X509_NAME_oneline(X509_get_issuer_name(
					sk_X509_value(sk, i)), buf, sizeof buf);
				BIO_printf(bio, "   i:%s\n", buf);
				if (c_showcerts)
					PEM_write_bio_X509(bio, sk_X509_value(sk, i));
			}
		}
		BIO_printf(bio, "---\n");
		peer = SSL_get_peer_certificate(s);
		if (peer != NULL) {
			BIO_printf(bio, "Server certificate\n");
			if (!(c_showcerts && got_a_chain))	/* Redundant if we
								 * showed the whole
								 * chain */
				PEM_write_bio_X509(bio, peer);
			X509_NAME_oneline(X509_get_subject_name(peer),
			    buf, sizeof buf);
			BIO_printf(bio, "subject=%s\n", buf);
			X509_NAME_oneline(X509_get_issuer_name(peer),
			    buf, sizeof buf);
			BIO_printf(bio, "issuer=%s\n", buf);
		} else
			BIO_printf(bio, "no peer certificate available\n");

		sk2 = SSL_get_client_CA_list(s);
		if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) {
			BIO_printf(bio, "---\nAcceptable client certificate CA names\n");
			for (i = 0; i < sk_X509_NAME_num(sk2); i++) {
				xn = sk_X509_NAME_value(sk2, i);
				X509_NAME_oneline(xn, buf, sizeof(buf));
				BIO_write(bio, buf, strlen(buf));
				BIO_write(bio, "\n", 1);
			}
		} else {
			BIO_printf(bio, "---\nNo client certificate CA names sent\n");
		}
		p = SSL_get_shared_ciphers(s, buf, sizeof buf);
		if (p != NULL) {
			/*
			 * This works only for SSL 2.  In later protocol
			 * versions, the client does not know what other
			 * ciphers (in addition to the one to be used in the
			 * current connection) the server supports.
			 */

			BIO_printf(bio, "---\nCiphers common between both SSL endpoints:\n");
			j = i = 0;
			while (*p) {
				if (*p == ':') {
					BIO_write(bio, space, 15 - j % 25);
					i++;
					j = 0;
					BIO_write(bio, ((i % 3) ? " " : "\n"), 1);
				} else {
					BIO_write(bio, p, 1);
					j++;
				}
				p++;
			}
			BIO_write(bio, "\n", 1);
		}
		BIO_printf(bio, "---\nSSL handshake has read %ld bytes and written %ld bytes\n",
		    BIO_number_read(SSL_get_rbio(s)),
		    BIO_number_written(SSL_get_wbio(s)));
	}
	BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, "));
	c = SSL_get_current_cipher(s);
	BIO_printf(bio, "%s, Cipher is %s\n",
	    SSL_CIPHER_get_version(c),
	    SSL_CIPHER_get_name(c));
	if (peer != NULL) {
		EVP_PKEY *pktmp;
		pktmp = X509_get_pubkey(peer);
		BIO_printf(bio, "Server public key is %d bit\n",
		    EVP_PKEY_bits(pktmp));
		EVP_PKEY_free(pktmp);
	}
	BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
	    SSL_get_secure_renegotiation_support(s) ? "" : " NOT");

	/* Compression is not supported and will always be none. */
	BIO_printf(bio, "Compression: NONE\n");
	BIO_printf(bio, "Expansion: NONE\n");

#ifdef SSL_DEBUG
	{
		/* Print out local port of connection: useful for debugging */
		int sock;
		struct sockaddr_in ladd;
		socklen_t ladd_size = sizeof(ladd);
		sock = SSL_get_fd(s);
		getsockname(sock, (struct sockaddr *) & ladd, &ladd_size);
		BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port));
	}
#endif

#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	if (next_proto.status != -1) {
		const unsigned char *proto;
		unsigned int proto_len;
		SSL_get0_next_proto_negotiated(s, &proto, &proto_len);
		BIO_printf(bio, "Next protocol: (%d) ", next_proto.status);
		BIO_write(bio, proto, proto_len);
		BIO_write(bio, "\n", 1);
	}
#endif

#ifndef OPENSSL_NO_SRTP
	{
		SRTP_PROTECTION_PROFILE *srtp_profile = SSL_get_selected_srtp_profile(s);

		if (srtp_profile)
			BIO_printf(bio, "SRTP Extension negotiated, profile=%s\n",
			    srtp_profile->name);
	}
#endif

	SSL_SESSION_print(bio, SSL_get_session(s));
	if (keymatexportlabel != NULL) {
		BIO_printf(bio, "Keying material exporter:\n");
		BIO_printf(bio, "    Label: '%s'\n", keymatexportlabel);
		BIO_printf(bio, "    Length: %i bytes\n", keymatexportlen);
		exportedkeymat = malloc(keymatexportlen);
		if (exportedkeymat != NULL) {
			if (!SSL_export_keying_material(s, exportedkeymat,
				keymatexportlen,
				keymatexportlabel,
				strlen(keymatexportlabel),
				NULL, 0, 0)) {
				BIO_printf(bio, "    Error\n");
			} else {
				BIO_printf(bio, "    Keying material: ");
				for (i = 0; i < keymatexportlen; i++)
					BIO_printf(bio, "%02X",
					    exportedkeymat[i]);
				BIO_printf(bio, "\n");
			}
			free(exportedkeymat);
		}
	}
	BIO_printf(bio, "---\n");
	if (peer != NULL)
		X509_free(peer);
	/* flush, or debugging output gets mixed with http response */
	(void) BIO_flush(bio);
}
Пример #24
0
/**
 * Accept the GSI Authentication.
 * @param sock the socket for communication.
 * @param ctx the authorization context.
 * @return the context identifier. 
 */
bool
GSISocketServer::AcceptGSIAuthentication()
{
  char *name = NULL;
  long  errorcode = 0;
  int   flags;

  time_t curtime, starttime;
  int ret, accept_status;
  bool accept_timed_out = false;
  int expected = 0;
  BIO *bio = NULL;
  char *cert_file, *user_cert, *user_key, *user_proxy;
  char *serial=NULL;

  cert_file = user_cert = user_key = user_proxy = NULL;

  if (proxy_get_filenames(0, &cert_file, &cacertdir, &user_proxy, &user_cert, &user_key) == 0) {
    (void)load_credentials(user_cert, user_key, &ucert, &own_stack, &upkey, NULL);
  }

  free(cert_file);
  free(user_cert);
  free(user_key);
  free(user_proxy);

  own_cert = ucert;
  own_key = upkey;
  ctx = SSL_CTX_new(SSLv23_method());
  SSL_CTX_load_verify_locations(ctx, NULL, cacertdir);
  SSL_CTX_use_certificate(ctx, ucert);
  SSL_CTX_use_PrivateKey(ctx,upkey);
  SSL_CTX_set_cipher_list(ctx, "ALL:!LOW:!EXP:!MD5:!MD2");    
  SSL_CTX_set_purpose(ctx, X509_PURPOSE_ANY);
  SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, proxy_verify_callback);
  SSL_CTX_set_verify_depth(ctx, 100);
  SSL_CTX_set_cert_verify_callback(ctx, proxy_app_verify_callback, 0);

  if (own_stack) {
    /*
     * Certificate was a proxy with a cert. chain.
     * Add the certificates one by one to the chain.
     */
    X509_STORE_add_cert(ctx->cert_store, ucert);
    for (int i = 0; i <sk_X509_num(own_stack); ++i) {
      X509 *cert = (sk_X509_value(own_stack,i));

      if (!X509_STORE_add_cert(ctx->cert_store, cert)) {
        if (ERR_GET_REASON(ERR_peek_error()) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
          ERR_clear_error();
          continue;
        }
        else {
          SetErrorOpenSSL("Cannot add certificate to the SSL context's certificate store");
          goto err;
        }
      }
    }
  }

  flags = fcntl(newsock, F_GETFL, 0);
  (void)fcntl(newsock, F_SETFL, flags | O_NONBLOCK);

  bio = BIO_new_socket(newsock, BIO_NOCLOSE);
  (void)BIO_set_nbio(bio, 1);

  ssl = SSL_new(ctx);
  setup_SSL_proxy_handler(ssl, cacertdir);

  writeb = bio->method->bwrite;
  readb  = bio->method->bread;
  bio->method->bwrite = globusf_write;
  bio->method->bread  = globusf_read;

  SSL_set_bio(ssl, bio, bio);

  curtime = starttime = time(NULL);

  ret = accept_status = -1;
  expected = 0;

  do {

    ret = do_select(newsock, starttime, timeout, expected);
    LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Select status: %d",ret);

    curtime = time(NULL);


    if (ret == 0){

      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Select timed out.");

      if (curtime - starttime > timeout){
        accept_timed_out = true;
        break;

      }else{

        continue;
      }
      
    }
    
    if (ret > 0) {
      accept_status = SSL_accept(ssl);
      curtime = time(NULL);
      expected = errorcode = SSL_get_error(ssl, accept_status);

      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Accept status: %d",accept_status);
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Error code: %d",errorcode);
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "SSL_WANT_READ: %d, SSL_WANT_WRITE: %d",SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE);
    }

    if (ret < 0)
      // No more data from the select
      break;

    if (accept_status == 1)
      // SSL handshake completed
      break;

    if (timeout != -1 && (curtime - starttime > timeout)){
      // Timeout reached
      accept_timed_out = true;
      break;
    }

    if (accept_status <= 0 && ( errorcode != SSL_ERROR_WANT_READ && errorcode != SSL_ERROR_WANT_WRITE ))
      // SSL handshake error
      break;
    
  } while (true);
  
  // Error enstabilishing context
  if (accept_status != 1){

    LOGM(VARP, logh, LEV_INFO, T_PRE, "Error enstabilishing SSL context.");

    if (accept_timed_out){
      SetError("SSL Handshake failed due to server timeout!");
    }else{
      SetErrorOpenSSL("SSL Handshake error:");
    }

    goto err;
  }
  
  // Context enstabilished
  actual_cert = SSL_get_peer_certificate(ssl);
  peer_stack  = SSL_get_peer_cert_chain(ssl);

  char buffer[1000];

//  if (LogLevelMin(logh, LEV_DEBUG)) {
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate DN: %s",
           X509_NAME_oneline(X509_get_subject_name(actual_cert), buffer, 999));
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate CA: %s",
           X509_NAME_oneline(X509_get_issuer_name(actual_cert), buffer, 999));
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Stack Size: %d", sk_X509_num(peer_stack));
//  }

  peer_cert = get_real_cert(actual_cert, peer_stack);

  if (peer_cert) {
    char *name = X509_NAME_oneline(X509_get_subject_name(peer_cert), NULL, 0);
    own_subject = std::string(name);
    OPENSSL_free(name);
  }

  if (LogLevelMin(logh, LEV_DEBUG)){
    for (int i = 0; i < sk_X509_num(peer_stack); i++) {
      X509 *cert = sk_X509_value(peer_stack, i);
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate DN: %s",
           X509_NAME_oneline(X509_get_subject_name(cert), buffer, 999));
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate CA: %s",
           X509_NAME_oneline(X509_get_issuer_name(cert), buffer, 999));
    }
  }

  name = X509_NAME_oneline(X509_get_subject_name(peer_cert), NULL, 0);
  if (name)
    peer_subject = std::string(name); 
  OPENSSL_free(name);

  name = X509_NAME_oneline(X509_get_issuer_name(peer_cert), NULL, 0);
  if (name)
    peer_ca = std::string(name);
  OPENSSL_free(name);

  serial = get_peer_serial(actual_cert);
  peer_serial = std::string(serial ? serial : "");
  OPENSSL_free(serial);

  return true;

err:
  destroy_SSL_proxy_handler(ssl);
  SSL_free(ssl);
  SSL_CTX_free(ctx);

  return false;
}
Пример #25
0
static int
mta_verify_certificate(struct mta_session *s)
{
#define MAX_CERTS	16
#define MAX_CERT_LEN	(MAX_IMSGSIZE - (IMSG_HEADER_SIZE + sizeof(req_ca_vrfy)))
	struct ca_vrfy_req_msg	req_ca_vrfy;
	struct iovec		iov[2];
	X509		       *x;
	STACK_OF(X509)	       *xchain;
	const char	       *name;
	unsigned char	       *cert_der[MAX_CERTS];
	int			cert_len[MAX_CERTS];
	int			i, cert_count, res;

	res = 0;
	memset(cert_der, 0, sizeof(cert_der));
	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);

	/* Send the client certificate */
	if (s->relay->ca_name) {
		name = s->relay->ca_name;
		req_ca_vrfy.fallback = 0;
	}
	else {
		name = s->helo;
		req_ca_vrfy.fallback = 1;
	}
	if (strlcpy(req_ca_vrfy.name, name, sizeof req_ca_vrfy.name)
	    >= sizeof req_ca_vrfy.name)
		return 0;

	x = SSL_get_peer_certificate(s->io.ssl);
	if (x == NULL)
		return 0;
	xchain = SSL_get_peer_cert_chain(s->io.ssl);

	/*
	 * Client provided a certificate and possibly a certificate chain.
	 * SMTP can't verify because it does not have the information that
	 * it needs, instead it will pass the certificate and chain to the
	 * lookup process and wait for a reply.
	 *
	 */

	cert_len[0] = i2d_X509(x, &cert_der[0]);
	X509_free(x);

	if (cert_len[0] < 0) {
		log_warnx("warn: failed to encode certificate");
		goto end;
	}
	log_debug("debug: certificate 0: len=%d", cert_len[0]);
	if (cert_len[0] > (int)MAX_CERT_LEN) {
		log_warnx("warn: certificate too long");
		goto end;
	}

	if (xchain) {
		cert_count = sk_X509_num(xchain);
		log_debug("debug: certificate chain len: %d", cert_count);
		if (cert_count >= MAX_CERTS) {
			log_warnx("warn: certificate chain too long");
			goto end;
		}
	}
	else
		cert_count = 0;

	for (i = 0; i < cert_count; ++i) {
		x = sk_X509_value(xchain, i);
		cert_len[i+1] = i2d_X509(x, &cert_der[i+1]);
		if (cert_len[i+1] < 0) {
			log_warnx("warn: failed to encode certificate");
			goto end;
		}
		log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]);
		if (cert_len[i+1] > (int)MAX_CERT_LEN) {
			log_warnx("warn: certificate too long");
			goto end;
		}
	}

	tree_xset(&wait_ssl_verify, s->id, s);
	s->flags |= MTA_WAIT;

	/* Send the client certificate */
	req_ca_vrfy.reqid = s->id;
	req_ca_vrfy.cert_len = cert_len[0];
	req_ca_vrfy.n_chain = cert_count;
	iov[0].iov_base = &req_ca_vrfy;
	iov[0].iov_len = sizeof(req_ca_vrfy);
	iov[1].iov_base = cert_der[0];
	iov[1].iov_len = cert_len[0];
	m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CERT, 0, 0, -1,
	    iov, nitems(iov));

	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
	req_ca_vrfy.reqid = s->id;

	/* Send the chain, one cert at a time */
	for (i = 0; i < cert_count; ++i) {
		req_ca_vrfy.cert_len = cert_len[i+1];
		iov[1].iov_base = cert_der[i+1];
		iov[1].iov_len  = cert_len[i+1];
		m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CHAIN, 0, 0, -1,
		    iov, nitems(iov));
	}

	/* Tell lookup process that it can start verifying, we're done */
	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
	req_ca_vrfy.reqid = s->id;
	m_compose(p_lka, IMSG_MTA_TLS_VERIFY, 0, 0, -1,
	    &req_ca_vrfy, sizeof req_ca_vrfy);

	res = 1;

    end:
	for (i = 0; i < MAX_CERTS; ++i)
		free(cert_der[i]);

	return res;
}
Пример #26
0
int main(int argc, char *argv[]) {
	int sd, ocsp_status;
	const unsigned char *p;
	long len;
	OCSP_RESPONSE *rsp = NULL;
	OCSP_BASICRESP *br = NULL;
	X509_STORE     *st = NULL;
	STACK_OF(X509) *ch = NULL;
	char *host, *port;
#ifdef _PATH_SSL_CA_FILE
	char *cafile = _PATH_SSL_CA_FILE;
#else
	char *cafile = "/etc/ssl/cert.pem";
#endif

	SSL *ssl;
	SSL_CTX *ctx;

	SSL_library_init();
	SSL_load_error_strings();

	ctx = SSL_CTX_new(SSLv23_client_method());

	if (!SSL_CTX_load_verify_locations(ctx, cafile, NULL)) {
		printf("failed to load %s\n", cafile);
		exit(-1);
	}

	if (argc != 3)
		errx(-1, "need a host and port to connect to");
	else {
		host = argv[1];
		port = argv[2];
	}

	sd = tcp_connect(host, port);

	ssl = SSL_new(ctx);

	SSL_set_fd(ssl, (int) sd);
	SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);

	if (SSL_connect(ssl) <= 0) {
		printf("SSL connect error\n");
		exit(-1);
	}

	if (SSL_get_verify_result(ssl) != X509_V_OK) {
		printf("Certificate doesn't verify from host %s port %s\n", host, port);
		exit(-1);
	}

	/* ==== VERIFY OCSP RESPONSE ==== */


	len = SSL_get_tlsext_status_ocsp_resp(ssl, &p);

	if (!p) {
		printf("No OCSP response received for %s port %s\n", host, port);
		exit(-1);
	}

	rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
	if (!rsp) {
		puts("Invalid OCSP response");
		exit(-1);
	}

	ocsp_status = OCSP_response_status(rsp);
	if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
		printf("Invalid OCSP response status: %s (%d)",
		       OCSP_response_status_str(ocsp_status), ocsp_status);
		exit(-1);
	}

	br = OCSP_response_get1_basic(rsp);
	if (!br) {
		puts("Invalid OCSP response");
		exit(-1);
	}

	ch = SSL_get_peer_cert_chain(ssl);
	st = SSL_CTX_get_cert_store(ctx);

	if (OCSP_basic_verify(br, ch, st, 0) <= 0) {
		puts("OCSP response verification failed");
		exit(-1);
	}

	printf("OCSP validated from %s %s\n", host, port);

	return 0;
}
Пример #27
0
bool SSLSocket::enableCrypto(bool activate /* = true */) {
  if (activate && !m_data->m_ssl_active) {
    double timeout = m_data->m_connect_timeout;
    bool blocked = m_data->m_is_blocked;
    if (!m_data->m_state_set) {
      if (m_data->m_client) {
        SSL_set_connect_state(m_data->m_handle);
      } else {
        SSL_set_accept_state(m_data->m_handle);
      }
      m_data->m_state_set = true;
    }

    if (m_data->m_client && setBlocking(false)) {
      m_data->m_is_blocked = false;
    }

    int n;
    bool retry = true;
    do {
      if (m_data->m_client) {
        struct timeval tvs, tve;
        struct timezone tz;

        gettimeofday(&tvs, &tz);
        n = SSL_connect(m_data->m_handle);
        gettimeofday(&tve, &tz);

        timeout -= (tve.tv_sec + (double) tve.tv_usec / 1000000) -
          (tvs.tv_sec + (double) tvs.tv_usec / 1000000);
        if (timeout < 0) {
          raise_warning("SSL: connection timeout");
          return -1;
        }
      } else {
        n = SSL_accept(m_data->m_handle);
      }

      if (n <= 0) {
        retry = handleError(n, true);
      } else {
        break;
      }
    } while (retry);

    if (m_data->m_client &&
        m_data->m_is_blocked != blocked &&
        setBlocking(blocked)) {
      m_data->m_is_blocked = blocked;
    }

    if (n == 1) {
      X509 *peer_cert = SSL_get_peer_certificate(m_data->m_handle);
      if (!applyVerificationPolicy(peer_cert)) {
        SSL_shutdown(m_data->m_handle);
      } else {
        m_data->m_ssl_active = true;

        /* allow the script to capture the peer cert
         * and/or the certificate chain */
        if (m_context[s_capture_peer_cert].toBoolean()) {
          m_context.set(s_peer_certificate,
                        Variant(makeSmartPtr<Certificate>(peer_cert)));
          peer_cert = nullptr;
        }

        if (m_context[s_capture_peer_cert_chain].toBoolean()) {
          Array arr;
          STACK_OF(X509) *chain = SSL_get_peer_cert_chain(m_data->m_handle);
          if (chain) {
            for (int i = 0; i < sk_X509_num(chain); i++) {
              X509 *mycert = X509_dup(sk_X509_value(chain, i));
              arr.append(Variant(makeSmartPtr<Certificate>(mycert)));
            }
          }
          m_context.set(s_peer_certificate_chain, arr);
        }
      }

      if (peer_cert) {
        X509_free(peer_cert);
      }
    } else  {
      n = errno == EAGAIN ? 0 : -1;
    }

    return n >= 0;

  } else if (!activate && m_data->m_ssl_active) {
    /* deactivate - common for server/client */
    SSL_shutdown(m_data->m_handle);
    m_data->m_ssl_active = false;
  }
  return true;
}
Пример #28
0
extern "C" X509Stack* CryptoNative_SslGetPeerCertChain(SSL* ssl)
{
    return SSL_get_peer_cert_chain(ssl);
}
Пример #29
0
static void print_stuff(BIO *bio, SSL *s, int full)
{
    X509 *peer=NULL;
    char *p;
    static const char *space="                ";
    char buf[BUFSIZ];
    STACK_OF(X509) *sk;
    STACK_OF(X509_NAME) *sk2;
    SSL_CIPHER *c;
    X509_NAME *xn;
    int j,i;
#ifndef OPENSSL_NO_COMP
    const COMP_METHOD *comp, *expansion;
#endif

    if (full)
    {
        int got_a_chain = 0;

        sk=SSL_get_peer_cert_chain(s);
        if (sk != NULL)
        {
            got_a_chain = 1; /* we don't have it for SSL2 (yet) */

            BIO_printf(bio,"---\nCertificate chain\n");
            for (i=0; i<sk_X509_num(sk); i++)
            {
                X509_NAME_oneline(X509_get_subject_name(
                                      sk_X509_value(sk,i)),buf,sizeof buf);
                BIO_printf(bio,"%2d s:%s\n",i,buf);
                X509_NAME_oneline(X509_get_issuer_name(
                                      sk_X509_value(sk,i)),buf,sizeof buf);
                BIO_printf(bio,"   i:%s\n",buf);
                if (c_showcerts)
                    PEM_write_bio_X509(bio,sk_X509_value(sk,i));
            }
        }

        BIO_printf(bio,"---\n");
        peer=SSL_get_peer_certificate(s);
        if (peer != NULL)
        {
            BIO_printf(bio,"Server certificate\n");
            if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */
                PEM_write_bio_X509(bio,peer);
            X509_NAME_oneline(X509_get_subject_name(peer),
                              buf,sizeof buf);
            BIO_printf(bio,"subject=%s\n",buf);
            X509_NAME_oneline(X509_get_issuer_name(peer),
                              buf,sizeof buf);
            BIO_printf(bio,"issuer=%s\n",buf);
        }
        else
            BIO_printf(bio,"no peer certificate available\n");

        sk2=SSL_get_client_CA_list(s);
        if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0))
        {
            BIO_printf(bio,"---\nAcceptable client certificate CA names\n");
            for (i=0; i<sk_X509_NAME_num(sk2); i++)
            {
                xn=sk_X509_NAME_value(sk2,i);
                X509_NAME_oneline(xn,buf,sizeof(buf));
                BIO_write(bio,buf,strlen(buf));
                BIO_write(bio,"\n",1);
            }
        }
        else
        {
            BIO_printf(bio,"---\nNo client certificate CA names sent\n");
        }
        p=SSL_get_shared_ciphers(s,buf,sizeof buf);
        if (p != NULL)
        {
            /* This works only for SSL 2.  In later protocol
             * versions, the client does not know what other
             * ciphers (in addition to the one to be used
             * in the current connection) the server supports. */

            BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n");
            j=i=0;
            while (*p)
            {
                if (*p == ':')
                {
                    BIO_write(bio,space,15-j%25);
                    i++;
                    j=0;
                    BIO_write(bio,((i%3)?" ":"\n"),1);
                }
                else
                {
                    BIO_write(bio,p,1);
                    j++;
                }
                p++;
            }
            BIO_write(bio,"\n",1);
        }

        BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
                   BIO_number_read(SSL_get_rbio(s)),
                   BIO_number_written(SSL_get_wbio(s)));
    }
    BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
    c=SSL_get_current_cipher(s);
    BIO_printf(bio,"%s, Cipher is %s\n",
               SSL_CIPHER_get_version(c),
               SSL_CIPHER_get_name(c));
    if (peer != NULL) {
        EVP_PKEY *pktmp;
        pktmp = X509_get_pubkey(peer);
        BIO_printf(bio,"Server public key is %d bit\n",
                   EVP_PKEY_bits(pktmp));
        EVP_PKEY_free(pktmp);
    }
#ifndef OPENSSL_NO_COMP
    comp=SSL_get_current_compression(s);
    expansion=SSL_get_current_expansion(s);
    BIO_printf(bio,"Compression: %s\n",
               comp ? SSL_COMP_get_name(comp) : "NONE");
    BIO_printf(bio,"Expansion: %s\n",
               expansion ? SSL_COMP_get_name(expansion) : "NONE");
#endif
    SSL_SESSION_print(bio,SSL_get_session(s));
    BIO_printf(bio,"---\n");
    if (peer != NULL)
        X509_free(peer);
    /* flush, or debugging output gets mixed with http response */
    (void)BIO_flush(bio);
}
Пример #30
0
static int
do_ca_cert_bootstrap(struct vconn *vconn)
{
    struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
    STACK_OF(X509) *chain;
    X509 *ca_cert;
    FILE *file;
    int error;
    int fd;

    chain = SSL_get_peer_cert_chain(sslv->ssl);
    if (!chain || !sk_X509_num(chain)) {
        VLOG_ERR("could not bootstrap CA cert: no certificate presented by "
                 "peer");
        return EPROTO;
    }
    ca_cert = sk_X509_value(chain, sk_X509_num(chain) - 1);

    /* Check that 'ca_cert' is self-signed.  Otherwise it is not a CA
     * certificate and we should not attempt to use it as one. */
    error = X509_check_issued(ca_cert, ca_cert);
    if (error) {
        VLOG_ERR("could not bootstrap CA cert: obtained certificate is "
                 "not self-signed (%s)",
                 X509_verify_cert_error_string(error));
        if (sk_X509_num(chain) < 2) {
            VLOG_ERR("only one certificate was received, so probably the peer "
                     "is not configured to send its CA certificate");
        }
        return EPROTO;
    }

    fd = open(ca_cert_file, O_CREAT | O_EXCL | O_WRONLY, 0444);
    if (fd < 0) {
        VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s",
                 ca_cert_file, strerror(errno));
        return errno;
    }

    file = fdopen(fd, "w");
    if (!file) {
        int error = errno;
        VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s",
                 strerror(error));
        unlink(ca_cert_file);
        return error;
    }

    if (!PEM_write_X509(file, ca_cert)) {
        VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: "
                 "%s", ca_cert_file, ERR_error_string(ERR_get_error(), NULL));
        fclose(file);
        unlink(ca_cert_file);
        return EIO;
    }

    if (fclose(file)) {
        int error = errno;
        VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s",
                 ca_cert_file, strerror(error));
        unlink(ca_cert_file);
        return error;
    }

    VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert_file);
    log_ca_cert(ca_cert_file, ca_cert);
    bootstrap_ca_cert = false;
    has_ca_cert = true;

    /* SSL_CTX_add_client_CA makes a copy of ca_cert's relevant data. */
    SSL_CTX_add_client_CA(ctx, ca_cert);

    /* SSL_CTX_use_certificate() takes ownership of the certificate passed in.
     * 'ca_cert' is owned by sslv->ssl, so we need to duplicate it. */
    ca_cert = X509_dup(ca_cert);
    if (!ca_cert) {
        out_of_memory();
    }
    if (SSL_CTX_load_verify_locations(ctx, ca_cert_file, NULL) != 1) {
        VLOG_ERR("SSL_CTX_load_verify_locations: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        return EPROTO;
    }
    VLOG_INFO("killing successful connection to retry using CA cert");
    return EPROTO;
}