Пример #1
0
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
{
    X509_OBJECT *obj;
    int ret = 1;

    if (x == NULL)
        return 0;
    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    if (obj == NULL) {
        X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    obj->type = X509_LU_CRL;
    obj->data.crl = x;

    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);

    X509_OBJECT_up_ref_count(obj);

    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
        X509_OBJECT_free_contents(obj);
        OPENSSL_free(obj);
        X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE);
        ret = 0;
    } else
        sk_X509_OBJECT_push(ctx->objs, obj);

    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);

    return ret;
}
Пример #2
0
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
{
    X509_OBJECT *obj;
    int ret = 1;

    if (x == NULL)
        return 0;
    obj = OPENSSL_malloc(sizeof(*obj));
    if (obj == NULL) {
        X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    obj->type = X509_LU_X509;
    obj->data.x509 = x;

    CRYPTO_THREAD_write_lock(ctx->lock);

    X509_OBJECT_up_ref_count(obj);

    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
        X509_OBJECT_free_contents(obj);
        OPENSSL_free(obj);
        X509err(X509_F_X509_STORE_ADD_CERT,
                X509_R_CERT_ALREADY_IN_HASH_TABLE);
        ret = 0;
    } else
        sk_X509_OBJECT_push(ctx->objs, obj);

    CRYPTO_THREAD_unlock(ctx->lock);

    return ret;
}
Пример #3
0
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
{
    X509_OBJECT *obj;
    int ret = 1;

    if (x == NULL)
        return 0;
    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    if (obj == NULL) {
        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
        return 0;
    }
    obj->type = X509_LU_CRL;
    obj->data.crl = x;

    CRYPTO_MUTEX_lock_write(&ctx->objs_lock);

    X509_OBJECT_up_ref_count(obj);

    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
        X509_OBJECT_free_contents(obj);
        OPENSSL_free(obj);
        OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
        ret = 0;
    } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
        X509_OBJECT_free_contents(obj);
        OPENSSL_free(obj);
        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
        ret = 0;
    }

    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);

    return ret;
}
Пример #4
0
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
{
    X509_OBJECT *obj;
    int ret = 1;

    if (x == NULL)
        return 0;
    obj = X509_OBJECT_new();
    if (obj == NULL)
        return 0;
    obj->type = X509_LU_CRL;
    obj->data.crl = x;

    CRYPTO_THREAD_write_lock(ctx->lock);

    X509_OBJECT_up_ref_count(obj);

    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
        X509_OBJECT_free(obj);
        X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE);
        ret = 0;
    } else
        sk_X509_OBJECT_push(ctx->objs, obj);

    CRYPTO_THREAD_unlock(ctx->lock);

    return ret;
}
Пример #5
0
/**
  Verification callback function to override any existing callbacks in OpenSSL
  for intermediate certificate supports.

  @param[in]  Status   Original status before calling this callback.
  @param[in]  Context  X509 store context.

  @retval     1        Current X509 certificate is verified successfully.
  @retval     0        Verification failed.

**/
int
X509VerifyCb (
  IN int            Status,
  IN X509_STORE_CTX *Context
  )
{
  X509_OBJECT  *Obj;
  INTN         Error;
  INTN         Index;
  INTN         Count;

  Obj   = NULL;
  Error = (INTN) X509_STORE_CTX_get_error (Context);

  //
  // X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT and X509_V_ERR_UNABLE_TO_GET_ISSUER_
  // CERT_LOCALLY mean a X509 certificate is not self signed and its issuer
  // can not be found in X509_verify_cert of X509_vfy.c.
  // In order to support intermediate certificate node, we override the
  // errors if the certification is obtained from X509 store, i.e. it is
  // a trusted ceritifcate node that is enrolled by user.
  // Besides,X509_V_ERR_CERT_UNTRUSTED and X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
  // are also ignored to enable such feature.
  //
  if ((Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) ||
      (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) {
    Obj = (X509_OBJECT *) malloc (sizeof (X509_OBJECT));
    if (Obj == NULL) {
      return 0;
    }

    Obj->type      = X509_LU_X509;
    Obj->data.x509 = Context->current_cert;

    CRYPTO_w_lock (CRYPTO_LOCK_X509_STORE);

    if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
      Status = 1;
    } else {
      //
      // If any certificate in the chain is enrolled as trusted certificate,
      // pass the certificate verification.
      //
      if (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
        Count = (INTN) sk_X509_num (Context->chain);
        for (Index = 0; Index < Count; Index++) {
          Obj->data.x509 = sk_X509_value (Context->chain, (int) Index);
          if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
            Status = 1;
            break;
          }
        }
      }
    }

    CRYPTO_w_unlock (CRYPTO_LOCK_X509_STORE);
  }

  if ((Error == X509_V_ERR_CERT_UNTRUSTED) ||
      (Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) {
    Status = 1;
  }

  if (Obj != NULL) {
    OPENSSL_free (Obj);
  }

  return Status;
}
Пример #6
0
/* This function negociates a SSL session with the server.
 * This function sets the KMO error string. It returns 0, -1, -2, or -3.
 */ 
static int knp_negociate_ssl_session(struct knp_query *query, char *cert, k3p_proto *k3p) {
    int error = 0;
    SSL_METHOD *ssl_method;
    BIO *ssl_bio;
    
    kmod_log_msg(3, "knp_negociate_ssl_session() called.\n");
    
    /* Create the SSL driver. */
    struct knp_ssl_driver *driver = (struct knp_ssl_driver *) kmo_calloc(sizeof(struct knp_ssl_driver));
    assert(query->ssl_driver == NULL);
    query->ssl_driver = driver;
    
    ssl_method = SSLv3_client_method();
    if (ssl_method == NULL) {
    	kmo_seterror("cannot initialize SSL method");
	return -1;
    }
    
    driver->ssl_ctx = SSL_CTX_new(ssl_method);
    if (driver->ssl_ctx == NULL) {
    	kmo_seterror("cannot initialize SSL context");
	return -1;
    }

    driver->ssl = SSL_new(driver->ssl_ctx);
    if (driver->ssl == NULL) {
    	kmo_seterror("cannot initialize SSL session");
	return -1;
    }

    ssl_bio = BIO_new_socket(query->transfer.fd, BIO_NOCLOSE);
    if (ssl_bio == NULL) {
    	kmo_seterror("cannot initialize SSL BIO");
	return -1;
    }
    
    /* Set SSL BIO. 'ssl_bio' is owned by 'ssl', do not free. */
    SSL_set_bio(driver->ssl, ssl_bio, ssl_bio);
    
    /* If we have a certificate, set it in SSL. */
    if (cert) {
    	int i;
	BIO *cert_bio = NULL;
	X509 *cert_obj = NULL;
	X509_STORE *cert_store = NULL;
	X509_OBJECT x509_obj;
	kstr cert_buf;
	kstr_init(&cert_buf);

	/* Try. */
	do {
	    /* Recreate the certificate. */
	    kstr_append_cstr(&cert_buf, "-----BEGIN CERTIFICATE-----\n");
	    kstr_append_cstr(&cert_buf, cert);
	    kstr_append_cstr(&cert_buf, "-----END CERTIFICATE-----\n");

	    for (i = 0; i < cert_buf.slen; i++) {
		if (cert_buf.data[i] == '|') {
		    cert_buf.data[i] = '\n';
		}
	    }

	    /* Put the certificate text in a buffer. */
	    cert_bio = BIO_new_mem_buf(cert_buf.data, cert_buf.slen);

	    if (cert_bio == NULL) {
		kmo_seterror("cannot create SSL BIO for reading SSL certificate");
		error = -1;
		break;   
	    }

	    /* Create the certificate object with the buffer data. */
	    cert_obj = PEM_read_bio_X509(cert_bio, NULL, 0, NULL);

	    if (cert_obj == NULL) {
		kmo_seterror("cannot create SSL certificate");
		error = -1;
		break;
	    }

	    /* Add the certificate in the certificate store if it is not
	     * already present.
	     */

	    /* Get the certificate store. */
	    cert_store = SSL_CTX_get_cert_store(driver->ssl_ctx);

	    if (cert_store == NULL) {
		kmo_seterror("cannot get SSL certificate store");
		error = -1;
		break;
	    }

	    /* Understanding SSL's API is a daunting task. I've peeked at
	     * the source code and that code should work. For now. Sigh.
	     * Wouldn't it be nice if programmers bothered to make
	     * *library* APIs that are somewhat sane...
	     *
	     * Check if the certificate is already in the store.
	     */
	    x509_obj.type = X509_LU_X509;
	    x509_obj.data.x509 = cert_obj;

	    /* It seems the certificate is already in the store. */
	    if (X509_OBJECT_retrieve_match(cert_store->objs, &x509_obj)) {
		/* Void. */
	    }

	    /* Add the certificate in the store. We still own cert_obj after
	     * this call.
	     */
	    else if (X509_STORE_add_cert(cert_store, cert_obj) != 1) {
		kmo_seterror("cannot store SSL certificate");
		error = -1;
		break;
	    }

    	} while (0);

	if (cert_obj) X509_free(cert_obj);
	if (cert_bio) BIO_free(cert_bio);
	kstr_free(&cert_buf);
	
	if (error) return error;
    }

    /* If we need a certificate, require the server to send us its certificate. */
    SSL_set_verify(driver->ssl, cert ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);

    /* Loop until we connect or fail. */
    while (1) {
	error = SSL_connect(driver->ssl);

	/* We're connected. */
	if (error > 0) {
	    error = 0;
	    break;
	}

	else {
	    int ssl_error = SSL_get_error(driver->ssl, error);
	    error = 0;

	    /* SSL wants us to wait for reading data. */
	    if (ssl_error == SSL_ERROR_WANT_READ) {
	    	error = knp_query_wait_for_data(query, 1, "SSL negociation read failed", k3p);
		if (error) return error;
	    }

	    /* SSL wants us to wait for writing data. */
	    else if (ssl_error == SSL_ERROR_WANT_WRITE) {
		error = knp_query_wait_for_data(query, 0, "SSL negociation write failed", k3p);
		if (error) return error;
	    }

	    /* Life is tough. */
	    else {
		kmo_seterror("SSL negociation failed: %s", get_ssl_error_string(ssl_error));
        	return -1;
	    }
	}
    }

    /* Validate the server's certificate as needed. */
    if (cert) {

	/* Check if the server sent us a certificate. */
	X509 *peer_cert = SSL_get_peer_certificate(driver->ssl);

	if (peer_cert == NULL) {
	    kmo_seterror("the server did not send its SSL certificate");
	    return -1;
	}

	X509_free(peer_cert);

	/* Verify the certificate. */
	if (SSL_get_verify_result(driver->ssl) != X509_V_OK) {
	    kmo_seterror("the SSL certificate of the server is invalid");
	    return -1;
	}
    }
    
    return 0;
}