Beispiel #1
0
/* validate the certifcate stored in 'data' by querying the ocsp-responder */
int
ocsp_validate_cert(struct iked *env, struct iked_static_id *id,
    void *data, size_t len, struct iked_sahdr sh, uint8_t type)
{
	struct iked_ocsp_entry	*ioe;
	struct iked_ocsp	*ocsp;
	BIO			*rawcert = NULL, *bissuer = NULL;
	X509			*cert = NULL, *issuer = NULL;

	if ((ioe = calloc(1, sizeof(*ioe))) == NULL)
		return (-1);
	if ((ocsp = calloc(1, sizeof(*ocsp))) == NULL) {
		free(ioe);
		return (-1);
	}

	ocsp->ocsp_env = env;
	ocsp->ocsp_sh = sh;
	ocsp->ocsp_type = type;

	if ((rawcert = BIO_new_mem_buf(data, len)) == NULL ||
	    (cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
	    (bissuer = BIO_new_file(IKED_OCSP_ISSUER, "r")) == NULL ||
	    (issuer = PEM_read_bio_X509(bissuer, NULL, NULL, NULL)) == NULL ||
	    (ocsp->ocsp_cbio = BIO_new(BIO_s_socket())) == NULL ||
	    (ocsp->ocsp_req = OCSP_REQUEST_new()) == NULL ||
	    !(ocsp->ocsp_id = OCSP_cert_to_id(NULL, cert, issuer)) ||
	    !OCSP_request_add0_id(ocsp->ocsp_req, ocsp->ocsp_id))
		goto err;

	BIO_free(rawcert);
	BIO_free(bissuer);
	X509_free(cert);
	X509_free(issuer);

	ioe->ioe_ocsp = ocsp;
	TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry);

	/* request connection to ocsp-responder */
	proc_compose_imsg(&env->sc_ps, PROC_PARENT, -1,
	    IMSG_OCSP_FD, -1, NULL, 0);
	return (0);

 err:
	ca_sslerror(__func__);
	free(ioe);
	if (rawcert != NULL)
		BIO_free(rawcert);
	if (cert != NULL)
		X509_free(cert);
	if (bissuer != NULL)
		BIO_free(bissuer);
	if (issuer != NULL)
		X509_free(issuer);
	ocsp_validate_finish(ocsp, 0);	/* failed */
	return (-1);
}
Beispiel #2
0
/*
 * OCSP::Resquest
 */
static VALUE
ossl_ocspreq_alloc(VALUE klass)
{
    OCSP_REQUEST *req;
    VALUE obj;

    if (!(req = OCSP_REQUEST_new()))
        ossl_raise(eOCSPError, NULL);
    WrapOCSPReq(klass, obj, req);

    return obj;
}
/* Create an OCSP request for the given certificate; returning the
 * certificate ID in *certid and *issuer on success.  Returns the
 * request object on success, or NULL on error. */
static OCSP_REQUEST *create_request(X509_STORE_CTX *ctx, X509 *cert,
                                    OCSP_CERTID **certid,
                                    server_rec *s, apr_pool_t *p,
                                    SSLSrvConfigRec *sc)
{
    OCSP_REQUEST *req = OCSP_REQUEST_new();

    *certid = OCSP_cert_to_id(NULL, cert, ctx->current_issuer);
    if (!*certid || !OCSP_request_add0_id(req, *certid)) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01921)
                     "could not retrieve certificate id");
        ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
        return NULL;
    }

    if (sc->server->ocsp_use_request_nonce != FALSE) {
        OCSP_request_add1_nonce(req, 0, -1);
    }

    return req;
}
Beispiel #4
0
int SslOcspStapling::getRequestData(unsigned char *pReqData)
{
    int             len = -1;
    OCSP_REQUEST    *ocsp;
    OCSP_CERTID     *id;

    if (m_pCertId == NULL)
        return LS_FAIL;
    ocsp = OCSP_REQUEST_new();
    if (ocsp == NULL)
        return LS_FAIL;

    id = OCSP_CERTID_dup(m_pCertId);
    if (OCSP_request_add0_id(ocsp, id) != NULL)
    {
        len = i2d_OCSP_REQUEST(ocsp, &pReqData);
        if (len > 0)
            *pReqData = 0;
    }
    OCSP_REQUEST_free(ocsp);
    return  len;
}
/*
 * This function sends a OCSP request to a defined OCSP responder
 * and checks the OCSP response for correctness.
 */
static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert,
		      EAP_TLS_CONF *conf)
{
	OCSP_CERTID *certid;
	OCSP_REQUEST *req;
	OCSP_RESPONSE *resp;
	OCSP_BASICRESP *bresp = NULL;
	char *host = NULL;
	char *port = NULL;
	char *path = NULL;
	int use_ssl = -1;
	BIO *cbio;
	int ocsp_ok;
	int status;

	/* 
	 * Create OCSP Request 
	 */
	certid = OCSP_cert_to_id(NULL, client_cert, issuer_cert);
	req = OCSP_REQUEST_new();
	OCSP_request_add0_id(req, certid);
	OCSP_request_add1_nonce(req, NULL, 8);

	/* 
	 * Send OCSP Request and get OCSP Response
	 */

	/* Get OCSP responder URL */ 
	if(conf->ocsp_override_url) {
		OCSP_parse_url(conf->ocsp_url, &host, &port, &path, &use_ssl);
	}
	else {
		ocsp_parse_cert_url(client_cert, &host, &port, &path, &use_ssl);
	}
	
	DEBUG2("[ocsp] --> Responder URL = http://%s:%s%s", host, port, path);

	/* Setup BIO socket to OCSP responder */
	cbio = BIO_new_connect(host);
	BIO_set_conn_port(cbio, port);
	BIO_do_connect(cbio);

	/* Send OCSP request and wait for response */
	resp = OCSP_sendreq_bio(cbio, path, req);
	if(resp==0) {
		radlog(L_ERR, "Error: Couldn't get OCSP response");
		ocsp_ok = 0;
		goto ocsp_end;
	}

	/* Verify OCSP response */
	status = OCSP_response_status(resp);
	if(status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
		radlog(L_ERR, "Error: OCSP response status: %s", OCSP_response_status_str(status));
		ocsp_ok = 0;
		goto ocsp_end;
	}
	bresp = OCSP_response_get1_basic(resp);
	if(OCSP_check_nonce(req, bresp)!=1) {
		radlog(L_ERR, "Error: OCSP response has wrong nonce value");
		ocsp_ok = 0;
		goto ocsp_end;
	}
	if(OCSP_basic_verify(bresp, NULL, store, 0)!=1){
		radlog(L_ERR, "Error: Couldn't verify OCSP basic response");
		ocsp_ok = 0;
		goto ocsp_end;
	}
	
	ocsp_ok = 1; 

ocsp_end:
	/* Free OCSP Stuff */
	OCSP_REQUEST_free(req);
	OCSP_RESPONSE_free(resp);
	free(host);
	free(port);
	free(path);
	BIO_free_all(cbio);
	OCSP_BASICRESP_free(bresp);

	if (ocsp_ok) {
		DEBUG2("[ocsp] --> Certificate is valid!");
	} else {
		DEBUG2("[ocsp] --> Certificate has been expired/revoked!");
	}

	return ocsp_ok;
}
static ngx_int_t
ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
{
    int            len;
    u_char        *p;
    uintptr_t      escape;
    ngx_str_t      binary, base64;
    ngx_buf_t     *b;
    OCSP_CERTID   *id;
    OCSP_REQUEST  *ocsp;

    ocsp = OCSP_REQUEST_new();
    if (ocsp == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_REQUEST_new() failed");
        return NGX_ERROR;
    }

    id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
    if (id == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_cert_to_id() failed");
        goto failed;
    }

    if (OCSP_request_add0_id(ocsp, id) == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_request_add0_id() failed");
        OCSP_CERTID_free(id);
        goto failed;
    }

    len = i2d_OCSP_REQUEST(ocsp, NULL);
    if (len <= 0) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "i2d_OCSP_REQUEST() failed");
        goto failed;
    }

    binary.len = len;
    binary.data = ngx_palloc(ctx->pool, len);
    if (binary.data == NULL) {
        goto failed;
    }

    p = binary.data;
    len = i2d_OCSP_REQUEST(ocsp, &p);
    if (len <= 0) {
        ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
                      "i2d_OCSP_REQUEST() failed");
        goto failed;
    }

    base64.len = ngx_base64_encoded_length(binary.len);
    base64.data = ngx_palloc(ctx->pool, base64.len);
    if (base64.data == NULL) {
        goto failed;
    }

    ngx_encode_base64(&base64, &binary);

    escape = ngx_escape_uri(NULL, base64.data, base64.len,
                            NGX_ESCAPE_URI_COMPONENT);

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
                   "ssl ocsp request length %z, escape %d",
                   base64.len, (int) escape);

    len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
          + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
          + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
          + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(ctx->pool, len);
    if (b == NULL) {
        goto failed;
    }

    p = b->last;

    p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
    p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);

    if (ctx->uri.data[ctx->uri.len - 1] != '/') {
        *p++ = '/';
    }

    if (escape == 0) {
        p = ngx_cpymem(p, base64.data, base64.len);

    } else {
        p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
                                      NGX_ESCAPE_URI_COMPONENT);
    }

    p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
    p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
    p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
    *p++ = CR; *p++ = LF;

    /* add "\r\n" at the header end */
    *p++ = CR; *p++ = LF;

    b->last = p;
    ctx->request = b;

    OCSP_REQUEST_free(ocsp);

    return NGX_OK;

failed:

    OCSP_REQUEST_free(ocsp);

    return NGX_ERROR;
}
Beispiel #7
0
const char* bud_context_get_ocsp_req(bud_context_t* context,
                                     size_t* size,
                                     char** ocsp_request,
                                     size_t* ocsp_request_len) {
  STACK_OF(OPENSSL_STRING)* urls;
  OCSP_REQUEST* req;
  OCSP_CERTID* id;
  char* encoded;
  unsigned char* pencoded;
  size_t encoded_len;

  urls = NULL;
  id = NULL;
  encoded = NULL;

  /* Cached url */
  if (context->ocsp_url != NULL)
    goto has_url;

  urls = X509_get1_ocsp(context->cert);
  if (urls == NULL)
    goto done;

  context->ocsp_url = sk_OPENSSL_STRING_pop(urls);
  context->ocsp_url_len = strlen(context->ocsp_url);

has_url:
  if (context->ocsp_url == NULL)
    goto done;

  id = OCSP_CERTID_dup(context->ocsp_id);
  if (id == NULL)
    goto done;

  /* Create request */
  req = OCSP_REQUEST_new();
  if (req == NULL)
    goto done;
  if (!OCSP_request_add0_id(req, id))
    goto done;
  id = NULL;

  encoded_len = i2d_OCSP_REQUEST(req, NULL);
  encoded = malloc(encoded_len);
  if (encoded == NULL)
    goto done;

  pencoded = (unsigned char*) encoded;
  i2d_OCSP_REQUEST(req, &pencoded);
  OCSP_REQUEST_free(req);

  *ocsp_request = encoded;
  *ocsp_request_len = encoded_len;
  encoded = NULL;

done:
  if (id != NULL)
    OCSP_CERTID_free(id);
  if (urls != NULL)
    X509_email_free(urls);
  if (encoded != NULL)
    free(encoded);

  *size = context->ocsp_url_len;
  return context->ocsp_url;
}
Beispiel #8
0
int myproxy_ocsp_verify(X509 *cert, X509 *issuer) {
  BIO                   *bio = 0;
  int                   rc, reason, ssl, status;
  char                  *host = 0, *path = 0, *port = 0, *certdir = 0;
  char                  *aiaocspurl = 0, *chosenurl = 0;
  SSL_CTX               *ctx = 0;
  X509_LOOKUP           *lookup = NULL;
  X509_STORE            *store = 0;
  OCSP_CERTID           *id;
  OCSP_REQUEST          *req = 0;
  OCSP_RESPONSE         *resp = 0;
  OCSP_BASICRESP        *basic = 0;
  myproxy_ocspresult_t  result;
  ASN1_GENERALIZEDTIME  *producedAt, *thisUpdate, *nextUpdate;
  globus_result_t       res;

  if (!policy && !responder_url) {
      result = MYPROXY_OCSPRESULT_ERROR_NOTCONFIGURED;
      goto end;
  }

  result = MYPROXY_OCSPRESULT_ERROR_UNKNOWN;

  if (policy && strstr(policy, "aia")) {
      aiaocspurl = myproxy_get_aia_ocsp_uri(cert);
  }

  if (!responder_url && !aiaocspurl) {
      result = MYPROXY_OCSPRESULT_ERROR_NOTCONFIGURED;
      goto end;
  }

  chosenurl = aiaocspurl ? aiaocspurl : responder_url;
  if (!OCSP_parse_url(chosenurl, &host, &port, &path, &ssl)) {
    result = MYPROXY_OCSPRESULT_ERROR_BADOCSPADDRESS;
    goto end;
  }

  myproxy_log("querying OCSP responder at %s", chosenurl);

  if (!(req = OCSP_REQUEST_new())) {
    result = MYPROXY_OCSPRESULT_ERROR_OUTOFMEMORY;
    goto end;
  }

  id = OCSP_cert_to_id(0, cert, issuer);
  if (!id || !OCSP_request_add0_id(req, id)) goto end;
  if (usenonce) OCSP_request_add1_nonce(req, 0, -1);

  /* sign the request */
  if (sign_cert && sign_key &&
      !OCSP_request_sign(req, sign_cert, sign_key, EVP_sha1(), 0, 0)) {
    result = MYPROXY_OCSPRESULT_ERROR_SIGNFAILURE;
    goto end;
  }

  /* setup GSI context */
  store=X509_STORE_new();
  lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
  if (lookup == NULL) {
    result = MYPROXY_OCSPRESULT_ERROR_OUTOFMEMORY;
    goto end;
  }
  res = GLOBUS_GSI_SYSCONFIG_GET_CERT_DIR(&certdir);
  if (res != GLOBUS_SUCCESS) {
    verror_put_string("failed to find GSI CA cert directory");
    globus_error_to_verror(res);
    goto end;
  }
  X509_LOOKUP_add_dir(lookup, certdir, X509_FILETYPE_PEM);
  ctx = SSL_CTX_new(SSLv23_client_method());
  if (ctx == NULL) {
    result = MYPROXY_OCSPRESULT_ERROR_OUTOFMEMORY;
    goto end;
  }
  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
  SSL_CTX_set_cert_store(ctx, store);
  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);

  /* establish a connection to the OCSP responder */
  if (!(bio = my_connect(host, atoi(port), ssl, &ctx))) {
    result = MYPROXY_OCSPRESULT_ERROR_CONNECTFAILURE;
    goto end;
  }

  /* send the request and get a response */
  resp = OCSP_sendreq_bio(bio, path, req);
  if ((rc = OCSP_response_status(resp)) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
    switch (rc) {
      case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
        result = MYPROXY_OCSPRESULT_ERROR_MALFORMEDREQUEST; break;
      case OCSP_RESPONSE_STATUS_INTERNALERROR:
        result = MYPROXY_OCSPRESULT_ERROR_INTERNALERROR;    break;
      case OCSP_RESPONSE_STATUS_TRYLATER:
        result = MYPROXY_OCSPRESULT_ERROR_TRYLATER;         break;
      case OCSP_RESPONSE_STATUS_SIGREQUIRED:
        result = MYPROXY_OCSPRESULT_ERROR_SIGREQUIRED;      break;
      case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
        result = MYPROXY_OCSPRESULT_ERROR_UNAUTHORIZED;     break;
    }
    goto end;
  }

  /* verify the response */
  result = MYPROXY_OCSPRESULT_ERROR_INVALIDRESPONSE;
  if (!(basic = OCSP_response_get1_basic(resp))) goto end;
  if (usenonce && OCSP_check_nonce(req, basic) <= 0) goto end;

  if (!responder_cert ||
      (rc = OCSP_basic_verify(basic, responder_cert, store,
                              OCSP_TRUSTOTHER)) <= 0)
      if ((rc = OCSP_basic_verify(basic, NULL, store, 0)) <= 0) 
          goto end;

  if (!OCSP_resp_find_status(basic, id, &status, &reason, &producedAt,
                             &thisUpdate, &nextUpdate))
    goto end;
  if (!OCSP_check_validity(thisUpdate, nextUpdate, skew, maxage))
    goto end;

  /* All done.  Set the return code based on the status from the response. */
  if (status == V_OCSP_CERTSTATUS_REVOKED) {
    result = MYPROXY_OCSPRESULT_CERTIFICATE_REVOKED;
    myproxy_log("OCSP status revoked!");
  } else {
    result = MYPROXY_OCSPRESULT_CERTIFICATE_VALID;
    myproxy_log("OCSP status valid");
  }

end:
  if (result < 0 && result != MYPROXY_OCSPRESULT_ERROR_NOTCONFIGURED) {
      ssl_error_to_verror();
      myproxy_log("OCSP check failed");
      myproxy_log_verror();
  }
  if (bio) BIO_free_all(bio);
  if (host) OPENSSL_free(host);
  if (port) OPENSSL_free(port);
  if (path) OPENSSL_free(path);
  if (req) OCSP_REQUEST_free(req);
  if (resp) OCSP_RESPONSE_free(resp);
  if (basic) OCSP_BASICRESP_free(basic);
  if (ctx) SSL_CTX_free(ctx);   /* this does X509_STORE_free(store) */
  if (certdir) free(certdir);
  if (aiaocspurl) free(aiaocspurl);

  return result;
}
Beispiel #9
0
static int ocsp_check(CLI *c, X509_STORE_CTX *callback_ctx) {
    int error, retval=0;
    SOCKADDR_UNION addr;
    X509 *cert;
    X509 *issuer=NULL;
    OCSP_CERTID *certID;
    BIO *bio=NULL;
    OCSP_REQUEST *request=NULL;
    OCSP_RESPONSE *response=NULL;
    OCSP_BASICRESP *basicResponse=NULL;
    ASN1_GENERALIZEDTIME *revoked_at=NULL,
        *this_update=NULL, *next_update=NULL;
    int status, reason;

    /* connect specified OCSP server (responder) */
    c->fd=s_socket(c->opt->ocsp_addr.addr[0].sa.sa_family, SOCK_STREAM, 0,
        0, "OCSP: socket (auth_user)");
    if(c->fd<0)
        return 0; /* reject connection */
    memcpy(&addr, &c->opt->ocsp_addr.addr[0], sizeof addr);
    if(connect_blocking(c, &addr, addr_len(addr)))
        goto cleanup;
    s_log(LOG_DEBUG, "OCSP: server connected");

    /* get current certificate ID */
    cert=X509_STORE_CTX_get_current_cert(callback_ctx); /* get current cert */
    if(X509_STORE_CTX_get1_issuer(&issuer, callback_ctx, cert)!=1) {
        sslerror("OCSP: X509_STORE_CTX_get1_issuer");
        goto cleanup;
    }
    certID=OCSP_cert_to_id(0, cert, issuer);
    if(!certID) {
        sslerror("OCSP: OCSP_cert_to_id");
        goto cleanup;
    }

    /* build request */
    request=OCSP_REQUEST_new();
    if(!request) {
        sslerror("OCSP: OCSP_REQUEST_new");
        goto cleanup;
    }
    if(!OCSP_request_add0_id(request, certID)) {
        sslerror("OCSP: OCSP_request_add0_id");
        goto cleanup;
    }
    OCSP_request_add1_nonce(request, 0, -1);

    /* send the request and get a response */
    /* FIXME: this code won't work with ucontext threading */
    /* (blocking sockets are used) */
    bio=BIO_new_fd(c->fd, BIO_NOCLOSE);
    response=OCSP_sendreq_bio(bio, c->opt->ocsp_path, request);
    if(!response) {
        sslerror("OCSP: OCSP_sendreq_bio");
        goto cleanup;
    }
    error=OCSP_response_status(response);
    if(error!=OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        s_log(LOG_WARNING, "OCSP: Responder error: %d: %s",
            error, OCSP_response_status_str(error));
        goto cleanup;
    }
    s_log(LOG_DEBUG, "OCSP: Response received");

    /* verify the response */
    basicResponse=OCSP_response_get1_basic(response);
    if(!basicResponse) {
        sslerror("OCSP: OCSP_response_get1_basic");
        goto cleanup;
    }
    if(OCSP_check_nonce(request, basicResponse)<=0) {
        sslerror("OCSP: OCSP_check_nonce");
        goto cleanup;
    }
    if(OCSP_basic_verify(basicResponse, NULL,
            c->opt->revocation_store, c->opt->ocsp_flags)<=0) {
        sslerror("OCSP: OCSP_basic_verify");
        goto cleanup;
    }
    if(!OCSP_resp_find_status(basicResponse, certID, &status, &reason,
            &revoked_at, &this_update, &next_update)) {
        sslerror("OCSP: OCSP_resp_find_status");
        goto cleanup;
    }
    s_log(LOG_NOTICE, "OCSP: Status: %d: %s",
        status, OCSP_cert_status_str(status));
    log_time(LOG_INFO, "OCSP: This update", this_update);
    log_time(LOG_INFO, "OCSP: Next update", next_update);
    /* check if the response is valid for at least one minute */
    if(!OCSP_check_validity(this_update, next_update, 60, -1)) {
        sslerror("OCSP: OCSP_check_validity");
        goto cleanup;
    }
    if(status==V_OCSP_CERTSTATUS_REVOKED) {
        if(reason==-1)
            s_log(LOG_WARNING, "OCSP: Certificate revoked");
        else
            s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s",
                reason, OCSP_crl_reason_str(reason));
        log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at);
        goto cleanup;
    }
    retval=1; /* accept connection */
cleanup:
    if(bio)
        BIO_free_all(bio);
    if(issuer)
        X509_free(issuer);
    if(request)
        OCSP_REQUEST_free(request);
    if(response)
        OCSP_RESPONSE_free(response);
    if(basicResponse)
        OCSP_BASICRESP_free(basicResponse);
    closesocket(c->fd);
    c->fd=-1; /* avoid double close on cleanup */
    return retval;
}
Beispiel #10
0
static int openssl_ocsp_request_new(lua_State*L)
{
  OCSP_REQUEST *req = NULL;
  
  if (lua_isstring(L, 1))
  {
    BIO* bio = load_bio_object(L, 1);
    req = d2i_OCSP_REQUEST_bio(bio, NULL);
    /*
    if (!req)
    {
      BIO_reset(bio);
      req = PEM_read_bio_OCSP_REQUEST(bio, NULL, NULL);
    }
    */
    BIO_free(bio);
  }
  else
  {
    X509 *issuer = CHECK_OBJECT(1, X509, "openssl.x509");
    X509_NAME *iname = X509_get_subject_name(issuer);
    ASN1_BIT_STRING *ikey = X509_get0_pubkey_bitstr(issuer);

    OCSP_CERTID *id = NULL;
    OCSP_ONEREQ *one;
    char buf[1024];
    int nonce = lua_gettop(L) > 2 ? auxiliar_checkboolean(L, 3) : 0;
    req = OCSP_REQUEST_new();

    if (lua_istable(L, 2))
    {
      int len = lua_rawlen(L, 2);
      int i;
      for (i = 1; i <= len; i++)
      {
        lua_rawgeti(L, 2, i);
        if (auxiliar_isclass(L, "openssl.x509", -1))
        {
          X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509");
          id = OCSP_cert_to_id(NULL, cert, issuer);
          one = OCSP_request_add0_id(req, id);
        }
        else
        {
          size_t len;
          char *serial = (char *)luaL_checklstring(L, -1, &len);
          ASN1_INTEGER *sno = ASN1_INTEGER_new();
          BIO* bio = BIO_new(BIO_s_mem());
          BIO_write(bio, serial, len);
          if (a2i_ASN1_INTEGER(bio, sno, buf, 1024) == 1)
          {
            id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
            one = OCSP_request_add0_id(req, id);
          };
          ASN1_INTEGER_free(sno);
          BIO_free(bio);
        }
        lua_pop(L, 1);
      }
    }
    else if (auxiliar_isclass(L, "openssl.x509", 2))
    {
      X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509");
      id = OCSP_cert_to_id(NULL, cert, issuer);
      one = OCSP_request_add0_id(req, id);
    }
    else
    {
      ASN1_INTEGER *sno = ASN1_INTEGER_new();
      BIO* bio = load_bio_object(L, 2);

      if (a2i_ASN1_INTEGER(bio, sno, buf, 1024) == 1)
      {
        id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
        one = OCSP_request_add0_id(req, id);
      };
      ASN1_INTEGER_free(sno);
      BIO_free(bio);
    }
    if (nonce)
      OCSP_request_add1_nonce(req, NULL,  -1);
  }
  if(req) {
    PUSH_OBJECT(req, "openssl.ocsp_request");
  }else
    lua_pushnil(L);

  return 1;
}
Beispiel #11
0
static int ocsp_check(CLI *c, X509_STORE_CTX *callback_ctx) {
    int error, retval=0;
    X509 *cert;
    X509 *issuer=NULL;
    OCSP_CERTID *certID;
    OCSP_REQUEST *request=NULL;
    OCSP_RESPONSE *response=NULL;
    OCSP_BASICRESP *basicResponse=NULL;
    ASN1_GENERALIZEDTIME *revoked_at=NULL,
        *this_update=NULL, *next_update=NULL;
    int status, reason;

    /* get current certificate ID */
    cert=X509_STORE_CTX_get_current_cert(callback_ctx); /* get current cert */
    if(X509_STORE_CTX_get1_issuer(&issuer, callback_ctx, cert)!=1) {
        sslerror("OCSP: X509_STORE_CTX_get1_issuer");
        goto cleanup;
    }
    certID=OCSP_cert_to_id(0, cert, issuer);
    if(!certID) {
        sslerror("OCSP: OCSP_cert_to_id");
        goto cleanup;
    }

    /* build request */
    request=OCSP_REQUEST_new();
    if(!request) {
        sslerror("OCSP: OCSP_REQUEST_new");
        goto cleanup;
    }
    if(!OCSP_request_add0_id(request, certID)) {
        sslerror("OCSP: OCSP_request_add0_id");
        goto cleanup;
    }
    OCSP_request_add1_nonce(request, 0, -1);

    /* send the request and get a response */
    response=ocsp_get_response(c, request);
    if(!response)
        goto cleanup;
    error=OCSP_response_status(response);
    if(error!=OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        s_log(LOG_WARNING, "OCSP: Responder error: %d: %s",
            error, OCSP_response_status_str(error));
        goto cleanup;
    }
    s_log(LOG_DEBUG, "OCSP: Response received");

    /* verify the response */
    basicResponse=OCSP_response_get1_basic(response);
    if(!basicResponse) {
        sslerror("OCSP: OCSP_response_get1_basic");
        goto cleanup;
    }
    if(OCSP_check_nonce(request, basicResponse)<=0) {
        sslerror("OCSP: OCSP_check_nonce");
        goto cleanup;
    }
    if(OCSP_basic_verify(basicResponse, NULL,
            c->opt->revocation_store, c->opt->ocsp_flags)<=0) {
        sslerror("OCSP: OCSP_basic_verify");
        goto cleanup;
    }
    if(!OCSP_resp_find_status(basicResponse, certID, &status, &reason,
            &revoked_at, &this_update, &next_update)) {
        sslerror("OCSP: OCSP_resp_find_status");
        goto cleanup;
    }
    s_log(LOG_NOTICE, "OCSP: Status: %d: %s",
        status, OCSP_cert_status_str(status));
    log_time(LOG_INFO, "OCSP: This update", this_update);
    log_time(LOG_INFO, "OCSP: Next update", next_update);
    /* check if the response is valid for at least one minute */
    if(!OCSP_check_validity(this_update, next_update, 60, -1)) {
        sslerror("OCSP: OCSP_check_validity");
        goto cleanup;
    }
    if(status==V_OCSP_CERTSTATUS_REVOKED) {
        if(reason==-1)
            s_log(LOG_WARNING, "OCSP: Certificate revoked");
        else
            s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s",
                reason, OCSP_crl_reason_str(reason));
        log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at);
        goto cleanup;
    }
    retval=1; /* accept connection */
cleanup:
    if(issuer)
        X509_free(issuer);
    if(request)
        OCSP_REQUEST_free(request);
    if(response)
        OCSP_RESPONSE_free(response);
    if(basicResponse)
        OCSP_BASICRESP_free(basicResponse);
    return retval;
}
Beispiel #12
0
/* returns one of:
 * V_OCSP_CERTSTATUS_GOOD
 * V_OCSP_CERTSTATUS_REVOKED
 * V_OCSP_CERTSTATUS_UNKNOWN */
NOEXPORT int ocsp_request(CLI *c, X509_STORE_CTX *callback_ctx,
        OCSP_CERTID *cert_id, char *url) {
    int status=V_OCSP_CERTSTATUS_UNKNOWN;
    int reason;
    int ctx_err=X509_V_ERR_APPLICATION_VERIFICATION;
    OCSP_REQUEST *request=NULL;
    OCSP_RESPONSE *response=NULL;
    OCSP_BASICRESP *basic_response=NULL;
    ASN1_GENERALIZEDTIME *revoked_at=NULL,
        *this_update=NULL, *next_update=NULL;

    /* build request */
    request=OCSP_REQUEST_new();
    if(!request) {
        sslerror("OCSP: OCSP_REQUEST_new");
        goto cleanup;
    }
    if(!OCSP_request_add0_id(request, cert_id)) {
        sslerror("OCSP: OCSP_request_add0_id");
        goto cleanup;
    }
    OCSP_request_add1_nonce(request, NULL, -1);

    /* send the request and get a response */
    response=ocsp_get_response(c, request, url);
    if(!response)
        goto cleanup;
    status=OCSP_response_status(response);
    if(status!=OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        s_log(LOG_WARNING, "OCSP: Responder error: %d: %s",
            status, OCSP_response_status_str(status));
        goto cleanup;
    }
    s_log(LOG_DEBUG, "OCSP: Response received");

    /* verify the response */
    basic_response=OCSP_response_get1_basic(response);
    if(!basic_response) {
        sslerror("OCSP: OCSP_response_get1_basic");
        goto cleanup;
    }
    if(OCSP_check_nonce(request, basic_response)<=0) {
        s_log(LOG_WARNING, "OCSP: Invalid nonce");
        goto cleanup;
    }
    if(OCSP_basic_verify(basic_response, NULL,
            c->opt->revocation_store, c->opt->ocsp_flags)<=0) {
        sslerror("OCSP: OCSP_basic_verify");
        goto cleanup;
    }
    if(!OCSP_resp_find_status(basic_response, cert_id, &status, &reason,
            &revoked_at, &this_update, &next_update)) {
        sslerror("OCSP: OCSP_resp_find_status");
        goto cleanup;
    }
    s_log(LOG_NOTICE, "OCSP: Status: %s", OCSP_cert_status_str(status));
    log_time(LOG_INFO, "OCSP: This update", this_update);
    log_time(LOG_INFO, "OCSP: Next update", next_update);
    /* check if the response is valid for at least one minute */
    if(!OCSP_check_validity(this_update, next_update, 60, -1)) {
        sslerror("OCSP: OCSP_check_validity");
        status=V_OCSP_CERTSTATUS_UNKNOWN;
        goto cleanup;
    }
    switch(status) {
    case V_OCSP_CERTSTATUS_GOOD:
        break;
    case V_OCSP_CERTSTATUS_REVOKED:
        if(reason==-1)
            s_log(LOG_WARNING, "OCSP: Certificate revoked");
        else
            s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s",
                reason, OCSP_crl_reason_str(reason));
        log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at);
        ctx_err=X509_V_ERR_CERT_REVOKED;
        break;
    case V_OCSP_CERTSTATUS_UNKNOWN:
        s_log(LOG_WARNING, "OCSP: Unknown verification status");
    }
cleanup:
    if(request)
        OCSP_REQUEST_free(request);
    if(response)
        OCSP_RESPONSE_free(response);
    if(basic_response)
        OCSP_BASICRESP_free(basic_response);
    if(status!=V_OCSP_CERTSTATUS_GOOD)
        X509_STORE_CTX_set_error(callback_ctx, ctx_err);
    return status;
}