*Thanks for the quick answer*, actually command line is good as it would be
done in  a 
child process using a secure vault for password creation that no admin knows
anyway or makes up.
No human is involved is always the best solution. Can't trust those humans.

thanks.
I enclosed the  correct code solution below for anyone to see how to
programmatically create an OSCP request.


      ./OCSPrequest -help

Usage:
   ./OCSPrequest  <cert>  <issuer root>
eg:
    ./OCSPrequest 1000.pem   ./demoCA/cacert.pem


OCSPrequest.c
============

/**
 *   cc -o OCSPrequest -Wno-deprecated-declarations
-Wno-pointer-type-mismatch OCSPrequest.c -lcrypto
 *
 *
 * Origin: r redpath
 *
 *
 *  The fields in this structure are as follows:
 *  
 *  typedef struct {
 *    char            *url;
 *    X509            *cert;
 *    X509            *issuer;
 *    spc_x509store_t *store;
 *    X509            *sign_cert;
 *    EVP_PKEY        *sign_key;
 *    long            skew;
 *    long            maxage;
 *  } spc_ocsprequest_t;
 *  
 *  url
 *  Address of the OCSP responder to which to connect; this should always be
a
 *  URL that specifies either HTTP or HTTPS as the service. For example, 
 *  VeriSign's OCSP responder address is http://ocsp.verisign.com.
 *  
 *  cert
 *  Pointer to the certificate whose revocation status you want to check. 
 *  In many cases, this will likely come from the peer when establishing or
 *  renegotiating an SSL session.
 *  
 *  issuer
 *  Pointer to the certificate that issued the certificate whose revocation
 *  status you want to check. This should be a trusted root certificate.
 *  
 *  store
 *  Any information required for building an X509_STORE object internally. 
 *  This object will be used for verifying the OCSP responder's certificate.
 *  A full discussion of this object can be found in Recipe 10.5, but
basically
 *  it contains trusted certificates and CRLs that OpenSSL can use to verify 
 *  the validity of the certificate received from the OCSP responder.
 *  
 *  sign_cert
 *  An OCSP request can optionally be signed. Some servers require signed 
 *  requests. Any server will accept a signed request provided that the
server
 *  is able to verify the signature. If you want the request to be signed, 
 *  this field should be non-NULL and should be a pointer to the certificate
 *  to use to sign the request. If you are going to sign your request, you 
 *  should use a certificate that has been issued by a CA that is trusted by
 *  the OCSP responder so that the responder will be able to verify its
validity.
 *  
 *  sign_key
 *  If the sign_cert member is non-NULL, this member must be filled in with 
 *  a pointer to the private key to use in signing the request. It is
ignored
 *  if the sign_cert member is NULL.
 *  
 *  skew
 *  An OCSP response contains three time fields: thisUpdate, nextUpdate, and 
 *  producedAt. These fields must be checked to determine how reliable the 
 *  results from the responder are. For example, under no circumstance
should 
 *  thisUpdate ever be greater than nextUpdate. However, it is likely that
there
 *  will be some amount of clock skew between the server and the client.
skew 
 *  defines an acceptable amount of skew in units of seconds. It should be
set 
 *  <to a reasonably low value. In most cases, five seconds should work out
fine.
 *  
 *  maxage
 *  RFC 2560 OCSP responders are allowed to precompute responses to improve
response
 *  time by eliminating the need to sign a response for every request. There
are 
 *  obvious security implications if a server opts to do this, as we
discussed in 
 *  Recipe 10.1. The producedAt field in the response will contain the time
at which
 *  the response was computed, whether or not it was precomputed. The maxage
member
 *  specifies the maximum age in seconds of responses that should be
considered 
 *  acceptable. Setting maxage to 0 will effectively cause the producedAt
field in
 *  the response to be ignored and any otherwise acceptable response to be
accepted,
 *  regardless of its age. OpenSSL's command-line ocsp command defaults to
ignoring 
 *  the producedAt field. However, we think it is too risky to accept
precomputed 
 *  responses. Unfortunately, there is no way to completely disable the
acceptance
 *  of precomputed responses. The closest we can get is to set this value to
one 
 *  second, which is what we recommend you do.
 *  Querying an OCSP responder is actually a complex operation, even though
we are 
 *  effectively reducing the amount of work necessary for you to a single
function 
 *  call. Because of the complexity of the operation, a number of things can
go wrong,
 *  and so we have defined a sizable number of possible error codes. In some
cases,
 *  we have lumped a number of finer-grained errors into a single error
code, but
 *  the code presented here can easily be expanded to provide more detailed
error
 *  information.
 *   ************************/
  
  #include &lt;time.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include <openssl/ocsp.h>
  #include <openssl/bio.h>
  #include <openssl/ssl.h>
  #include <openssl/pem.h>
  #include <openssl/conf.h>
  #include <openssl/x509v3.h>
  #ifndef OPENSSL_NO_ENGINE
        #include <openssl/engine.h>
  #endif
  
  #define SPC_X509STORE_NO_DEFAULT_CAFILE 0x01
  #define SPC_X509STORE_NO_DEFAULT_CAPATH 0x02
  
  typedef int (*spc_x509verifycallback_t)(int, X509_STORE_CTX *);
  
typedef struct {
        char                      *cafile;
        char                      *capath;
        char                      *crlfile;
        spc_x509verifycallback_t  callback;
        STACK_OF(X509)            *certs;
        STACK_OF(X509_CRL)        *crls;
        char                      *use_certfile;
        STACK_OF(X509)            *use_certs;
        char                      *use_keyfile;
        EVP_PKEY                  *use_key;
        int                       flags;
} spc_x509store_t;


typedef struct {
        char            *url;
        X509            *cert;
        X509            *issuer;
        spc_x509store_t *store;
        X509            *sign_cert;
        EVP_PKEY        *sign_key;
        long            skew;
        long            maxage;
} spc_ocsprequest_t;


typedef enum {
        SPC_OCSPRESULT_ERROR_INVALIDRESPONSE   = -12,
        SPC_OCSPRESULT_ERROR_CONNECTFAILURE    = -11,
        SPC_OCSPRESULT_ERROR_SIGNFAILURE       = -10,
        SPC_OCSPRESULT_ERROR_BADOCSPADDRESS    = -9,
        SPC_OCSPRESULT_ERROR_OUTOFMEMORY       = -8,
        SPC_OCSPRESULT_ERROR_UNKNOWN           = -7,
        SPC_OCSPRESULT_ERROR_UNAUTHORIZED      = -6,
        SPC_OCSPRESULT_ERROR_SIGREQUIRED       = -5,
        SPC_OCSPRESULT_ERROR_TRYLATER          = -3,
        SPC_OCSPRESULT_ERROR_INTERNALERROR     = -2,
        SPC_OCSPRESULT_ERROR_MALFORMEDREQUEST  = -1,
        SPC_OCSPRESULT_CERTIFICATE_VALID       = 0,
        SPC_OCSPRESULT_CERTIFICATE_REVOKED     = 1
} spc_ocspresult_t;



/**
 *
 */
void spc_init_x509store(spc_x509store_t *spc_store) {
  spc_store->cafile       = 0;
  spc_store->capath       = 0;
  spc_store->crlfile      = 0;
  spc_store->callback     = 0;
  spc_store->certs        = sk_X509_new_null(  );
  spc_store->crls         = sk_X509_CRL_new_null(  );
  spc_store->use_certfile = 0;
  spc_store->use_certs    = sk_X509_new_null(  );
  spc_store->use_keyfile  = 0;
  spc_store->use_key      = 0;
  spc_store->flags        = 0;
}



/**
 *
 */
void spc_cleanup_x509store(spc_x509store_t *spc_store) {
        if (spc_store->cafile)           free(spc_store->cafile);
        if (spc_store->capath)           free(spc_store->capath);
        if (spc_store->crlfile)          free(spc_store->crlfile);
        if (spc_store->use_certfile) free(spc_store->use_certfile);
        if (spc_store->use_keyfile)      free(spc_store->use_keyfile);
        if (spc_store->use_key)          EVP_PKEY_free(spc_store->use_key);
        sk_X509_free(spc_store->certs);
        sk_X509_free(spc_store->crls);
        sk_X509_free(spc_store->use_certs);
}


/**
 *
 */
X509_STORE *spc_create_x509store(spc_x509store_t *spc_store) {
  int         i;
  X509_STORE  *store;
  X509_LOOKUP *lookup;
   
  store = X509_STORE_new(  );
  /**
 if (spc_store->callback)
    X509_STORE_set_verify_cb_func(store, spc_store->callback);
  else
    X509_STORE_set_verify_cb_func(store, spc_verify_callback);
  **/
   
  if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file(  ))))
    goto error_exit;

  if (!spc_store->cafile) {
    printf("no CAFILE \n");
    if (!(spc_store->flags & SPC_X509STORE_NO_DEFAULT_CAFILE))
      X509_LOOKUP_load_file(lookup, 0, X509_FILETYPE_DEFAULT);
  } else{
       if (!X509_LOOKUP_load_file(lookup, spc_store->cafile,
X509_FILETYPE_PEM))
       goto error_exit;
  }   
  if (spc_store->crlfile) {
    if (!X509_load_crl_file(lookup, spc_store->crlfile, X509_FILETYPE_PEM))
      goto error_exit;
    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
X509_V_FLAG_CRL_CHECK_ALL);
  }
   
  if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir(  ))))
    goto error_exit;
  if (!spc_store->capath) {
    if (!(spc_store->flags & SPC_X509STORE_NO_DEFAULT_CAPATH))
      X509_LOOKUP_add_dir(lookup, 0, X509_FILETYPE_DEFAULT);
  } else if (!X509_LOOKUP_add_dir(lookup, spc_store->capath,
X509_FILETYPE_PEM))
    goto error_exit;
   
  for (i = 0; i < sk_X509_num(spc_store->certs); i++)
    if (!X509_STORE_add_cert(store, sk_X509_value(spc_store->certs, i)))
      goto error_exit;
  for (i = 0; i < sk_X509_CRL_num(spc_store->crls); i++)
    if (!X509_STORE_add_crl(store, sk_X509_CRL_value(spc_store->crls, i)))
      goto error_exit;
   
  // printf("success spc_create_x509store\n");
  return store;
   
error_exit:
  printf("error_exit spc_create_x509store\n");
  
  if (store) X509_STORE_free(store);
  return 0;
}


/**
 *
 */
BIO *spc_connect(char *host, int port, int ssl, spc_x509store_t *spc_store,
SSL_CTX **ctx) { 
   BIO *conn; 
   /**
   SSL *ssl_ptr;  
   if (ssl) {
      if (!(conn = spc_connect_ssl(host, port, spc_store, ctx))) 
           goto error_exit;
      BIO_get_ssl(conn, &ssl_ptr); 
      if (!spc_verify_cert_hostname(SSL_get_peer_certificate(ssl_ptr),
host))
         goto error_exit;
      if (SSL_get_verify_result(ssl_ptr) != X509_V_OK) 
         goto error_exit;
      return conn;
   }
   **/
  *ctx = 0; 
  if (!(conn = BIO_new_connect(host))) 
     goto error_exit;
  BIO_set_conn_int_port(conn, &port); 
  if (BIO_do_connect(conn) <= 0) 
     goto error_exit;
  return conn; 
error_exit: 
  printf("error_exit  connect\n");
  
  if (conn) 
    BIO_free_all(conn);
  return 0;
} 




/**
 *
 */
spc_ocspresult_t spc_verify_via_ocsp(spc_ocsprequest_t *data) {
        BIO                   *bio = 0;
        int                   rc, reason, ssl, status;
        char                  *host = 0, *path = 0, *port = 0;
        SSL_CTX               *ctx = 0;
        X509_STORE            *store = 0;
        OCSP_CERTID           *id;
        OCSP_REQUEST          *req = 0;
        OCSP_RESPONSE         *resp = 0;
        OCSP_BASICRESP        *basic = 0;
        spc_ocspresult_t      result;
        ASN1_GENERALIZEDTIME  *producedAt, *thisUpdate, *nextUpdate;

        result = SPC_OCSPRESULT_ERROR_UNKNOWN;
        if (!OCSP_parse_url(data->url, &host, &port, &path, &ssl)) {
                result = SPC_OCSPRESULT_ERROR_BADOCSPADDRESS;
                goto end;
        }
        if (!(req = OCSP_REQUEST_new(  ))) {
                result = SPC_OCSPRESULT_ERROR_OUTOFMEMORY;
                goto end;
        }

//
//Here I guess is where you can add multiple certs" Right now we haev only
one 
//

        id = OCSP_cert_to_id(0, data->cert, data->issuer);
        if (!id || !OCSP_request_add0_id(req, id)) goto end;


//lets do it twice what the heck
//show how to do multiple x509s
//      id = OCSP_cert_to_id(0, data->cert, data->issuer);
//      if (!id || !OCSP_request_add0_id(req, id)) goto end;

        OCSP_request_add1_nonce(req, 0, -1);

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

        /* establish a connection to the OCSP responder */
        if (!(bio = spc_connect(host, atoi(port), ssl, data->store, &ctx))) {
                result = SPC_OCSPRESULT_ERROR_CONNECTFAILURE;
                goto end;
        }

        /* send the request and get a response */
        resp = OCSP_sendreq_bio(bio, path, req);
        if (resp==NULL)
          goto end;
        
        if ((rc = OCSP_response_status(resp)) != 
OCSP_RESPONSE_STATUS_SUCCESSFUL) {
                switch (rc) {
                case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
                        result = SPC_OCSPRESULT_ERROR_MALFORMEDREQUEST; break;
                case OCSP_RESPONSE_STATUS_INTERNALERROR:
                        result = SPC_OCSPRESULT_ERROR_INTERNALERROR;    break;
                case OCSP_RESPONSE_STATUS_TRYLATER:
                        result = SPC_OCSPRESULT_ERROR_TRYLATER;         break;
                case OCSP_RESPONSE_STATUS_SIGREQUIRED:
                        result = SPC_OCSPRESULT_ERROR_SIGREQUIRED;      break;
                case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
                        result = SPC_OCSPRESULT_ERROR_UNAUTHORIZED;     break;
                }
                goto end;
        }

        /* verify the response */
        result = SPC_OCSPRESULT_ERROR_INVALIDRESPONSE;
        if (!(basic = OCSP_response_get1_basic(resp))) goto end;

        if (OCSP_check_nonce(req, basic) <= 0) goto end;

        if (data->store && !(store = spc_create_x509store(data->store))) goto 
end;

        printf("verify signature\n");
        //verify signature
        if ((rc = OCSP_basic_verify(basic, 0, store, 0)) <= 0) goto end;

        if (!OCSP_resp_find_status(basic, id, &status, &reason, &producedAt,
                                   &thisUpdate, &nextUpdate)){
                printf("verify signature failed\n");
                goto end;
        }

        if (!OCSP_check_validity(thisUpdate, nextUpdate, data->skew, 
data->maxage))
                goto end;


        /* All done.  Set the return code based on the status from the 
response. */
        if (status == V_OCSP_CERTSTATUS_REVOKED)
                result = SPC_OCSPRESULT_CERTIFICATE_REVOKED;
        else
                result = SPC_OCSPRESULT_CERTIFICATE_VALID;

        end:

        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);
        if (store) X509_STORE_free(store);
        return result;
}



void help(){
  printf("\nUsage:\n");
  printf("   ./OCSPrequest  <cert>  <issuer root>\n");
  printf("eg:\n");
  printf("    ./OCSPrequest 1000.pem   ./demoCA/cacert.pem\n\n");
  exit(0);
}


/**
 *
 */
int main(int argc, char **argv){
  char *url= "http://127.0.0.1:8082";;              //For now our OCSP server
location
  char *x509file="./demoCA/newcerts/1000.pem";     //The x509 filename we
want to verify
  char *inCAcert="./demoCA/cacert.pem";
  X509 *x=NULL; 
  X509 *issuerRoot=NULL;

  switch (argc){
  case 1:  //defaults
    break;
  case 3:
     x509file= argv[1];
     inCAcert= argv[2];
     break;
  default:
    help();
  }
     
  printf("\nOCSP URL:       %s\n",url);
  printf("Cert checking:  %s\n",x509file);
  printf("Root issuer:    %s\n\n",inCAcert);

  ERR_load_BIO_strings();
  ERR_load_crypto_strings();
  OpenSSL_add_all_algorithms();
  OpenSSL_add_all_ciphers();
  OpenSSL_add_all_digests();



  //Load the X509 file
  //

   FILE *fp =fopen(x509file, "rb");
   if (fp==NULL) {
      printf("X509 File not found %s which is to be verified\n",x509file);
      return 1;
   }
   x=  PEM_read_X509(fp,&x, NULL, NULL); 
   if (x==NULL){
      fprintf(stderr,"null x509\n");
     return 1;
   }
   fclose(fp);


  //Load the X509 file
  //

   fp =fopen("./demoCA/cacert.pem", "rb");
   if (fp==NULL) {
      printf("X509 File not found %s which is to be verified\n",x509file);
      return 1;
   }
   issuerRoot=  PEM_read_X509(fp,&issuerRoot, NULL, NULL); 
   if (issuerRoot==NULL){
      fprintf(stderr,"null x509 issuer Root\n");
     return 1;
   }
   fclose(fp);


/**
typedef struct {
        char            *url;
        X509            *cert;
        X509            *issuer;
        spc_x509store_t *store;
        X509            *sign_cert;
        EVP_PKEY        *sign_key;
        long            skew;
        long            maxage;
} spc_ocsprequest_t;
 **/

  spc_ocsprequest_t *req= malloc(sizeof (spc_ocsprequest_t));
  req->url      = url;
  req->cert     = x;
  req->issuer   = issuerRoot;
  req->store    = malloc(sizeof(spc_x509store_t) );
  spc_init_x509store(req->store);
  req->store->cafile= inCAcert;

  req->sign_cert= NULL;      //OCSP request is not optionally signed
  req->sign_key = NULL;       
  req->skew     = 5;         //5 seconds
  req->maxage   = 1;         //recommended to set to one


  spc_ocspresult_t result= spc_verify_via_ocsp(req);

  switch (result){
  case 0:
    printf("Verify result GOOD\n");
    break;
  case 1:
    printf("Verify result  REVOKED\n");
  default:
    printf("ERROR Verify result is %d \n",result);
    break;
  }
  return 0;
}









--
View this message in context: 
http://openssl.6102.n7.nabble.com/OSCP-request-tp45835p45889.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to