Description of the patch:

This patch provides OCSP request handler using non blocking BIOs. The new added library routine is

OCSP_RESPONSE * OCSP_sendreq_bio_with_timeout(BIO *b, char *path, OCSP_REQUEST *req, long timeout)

*BIO *b* is a non blocking bio. The number of seconds you wish to use for timeout can be passed using *long timeout*.

It also provides *-timeout* option for OCSP client utilility.

It is against openssl-0.9.7d and it is tested on Solaris using gcc and on Windows using VC++.

Thanks,
Amar Desai


diff -ur ./openssl-0.9.7d-orig/apps/ocsp.c ./openssl-0.9.7d/apps/ocsp.c
--- ./openssl-0.9.7d-orig/apps/ocsp.c   2004-04-19 18:18:47.390001000 -0100
+++ ./openssl-0.9.7d/apps/ocsp.c        2004-04-20 10:57:26.470003000 -0100
@@ -112,7 +112,7 @@
        BIO *derbio = NULL;
        BIO *out = NULL;
        int req_text = 0, resp_text = 0;
-       long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
+       long nsec = MAX_VALIDITY_PERIOD, maxage = -1, timeout = 90;
        char *CAfile = NULL, *CApath = NULL;
        X509_STORE *store = NULL;
        SSL_CTX *ctx = NULL;
@@ -325,6 +325,22 @@
                                }
                        else badarg = 1;
                        }
+                else if (!strcmp (*args, "-timeout"))
+                       {
+                       if (args[1])
+                               {
+                               args++;
+                               timeout = atol(*args);
+                               if (timeout < 0)
+                                       {
+                                       BIO_printf(bio_err,
+                                               "Illegal timeout %s\n",
+                                               *args);
+                                       badarg = 1;
+                                       }
+                               }
+                       else badarg = 1;
+                       }       
                 else if (!strcmp(*args, "-signkey"))
                        {
                        if (args[1])
@@ -533,6 +549,7 @@
                BIO_printf (bio_err, "-VAfile file       validator certificates 
file\n");
                BIO_printf (bio_err, "-validity_period n maximum validity discrepancy 
in seconds\n");
                BIO_printf (bio_err, "-status_age n      maximum status age in 
seconds\n");
+               BIO_printf (bio_err, "-timeout n         timeout in seconds for ocsp 
client \n");
                BIO_printf (bio_err, "-noverify          don't verify response at 
all\n");
                BIO_printf (bio_err, "-verify_other file additional certificates to 
search for signer\n");
                BIO_printf (bio_err, "-trust_other       don't verify additional 
certificates\n");
@@ -712,6 +729,7 @@
                        goto end;
                        }
                if (port) BIO_set_conn_port(cbio, port);
+               BIO_set_nbio(cbio,1);
                if (use_ssl == 1)
                        {
                        BIO *sbio;
@@ -731,10 +749,11 @@
                        }
                if (BIO_do_connect(cbio) <= 0)
                        {
-                       BIO_printf(bio_err, "Error connecting BIO\n");
-                       goto end;
+                       /*BIO_printf(bio_err, "Error connecting BIO\n");
+                       goto end;*/
+                                       resp = OCSP_sendreq_bio_with_timeout(cbio, 
path,req,timeout);
                        }
-               resp = OCSP_sendreq_bio(cbio, path, req);
+
                BIO_free_all(cbio);
                cbio = NULL;
                if (!resp)
@@ -873,7 +892,7 @@
        X509_free(cert);
        X509_free(rsigner);
        X509_free(rca_cert);
-       free_index(rdb);
+       if(rdb != NULL) free_index(rdb);
        BIO_free_all(cbio);
        BIO_free_all(acbio);
        BIO_free(out);
diff -ur ./openssl-0.9.7d-orig/crypto/ocsp/ocsp.h ./openssl-0.9.7d/crypto/ocsp/ocsp.h
--- ./openssl-0.9.7d-orig/crypto/ocsp/ocsp.h    2004-04-19 18:19:04.840002000 -0100
+++ ./openssl-0.9.7d/crypto/ocsp/ocsp.h 2004-04-20 10:48:10.900002000 -0100
@@ -404,6 +404,8 @@
                (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
 
 OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_sendreq_bio_with_timeout(BIO *b, char *path, OCSP_REQUEST *req, 
long timeout);
+
 
 OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
 
@@ -579,6 +581,7 @@
 #define OCSP_F_OCSP_REQUEST_VERIFY                      116
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC                         111
 #define OCSP_F_OCSP_SENDREQ_BIO                                 112
+#define OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT            117
 #define OCSP_F_REQUEST_VERIFY                           113
 
 /* Reason codes. */
@@ -612,6 +615,9 @@
 #define OCSP_R_UNKNOWN_MESSAGE_DIGEST                   119
 #define OCSP_R_UNKNOWN_NID                              120
 #define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE           129
+#define OCSP_R_SERVER_CONNECT_ERROR                     130
+#define OCSP_R_SERVER_TIMEOUT_ERROR                     131
+
 
 #ifdef  __cplusplus
 }
diff -ur ./openssl-0.9.7d-orig/crypto/ocsp/ocsp_err.c 
./openssl-0.9.7d/crypto/ocsp/ocsp_err.c
--- ./openssl-0.9.7d-orig/crypto/ocsp/ocsp_err.c        2004-04-19 18:19:04.800000000 
-0100
+++ ./openssl-0.9.7d/crypto/ocsp/ocsp_err.c     2004-04-20 10:14:25.270002000 -0100
@@ -82,6 +82,7 @@
 {ERR_PACK(0,OCSP_F_OCSP_REQUEST_VERIFY,0),     "OCSP_request_verify"},
 {ERR_PACK(0,OCSP_F_OCSP_RESPONSE_GET1_BASIC,0),        "OCSP_response_get1_basic"},
 {ERR_PACK(0,OCSP_F_OCSP_SENDREQ_BIO,0),        "OCSP_sendreq_bio"},
+{ERR_PACK(0,OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,0),"OCSP_sendreq_bio_with_timeout"},
 {ERR_PACK(0,OCSP_F_REQUEST_VERIFY,0),  "REQUEST_VERIFY"},
 {0,NULL}
        };
@@ -110,6 +111,8 @@
 {OCSP_R_SERVER_RESPONSE_ERROR            ,"server response error"},
 {OCSP_R_SERVER_RESPONSE_PARSE_ERROR      ,"server response parse error"},
 {OCSP_R_SERVER_WRITE_ERROR               ,"server write error"},
+{OCSP_R_SERVER_CONNECT_ERROR            ,"server connect error"},
+{OCSP_R_SERVER_TIMEOUT_ERROR            ,"server timeout error"}, 
 {OCSP_R_SIGNATURE_FAILURE                ,"signature failure"},
 {OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND     ,"signer certificate not found"},
 {OCSP_R_STATUS_EXPIRED                   ,"status expired"},
diff -ur ./openssl-0.9.7d-orig/crypto/ocsp/ocsp_ht.c 
./openssl-0.9.7d/crypto/ocsp/ocsp_ht.c
--- ./openssl-0.9.7d-orig/crypto/ocsp/ocsp_ht.c 2004-04-19 18:19:04.859999000 -0100
+++ ./openssl-0.9.7d/crypto/ocsp/ocsp_ht.c      2004-04-20 10:49:14.990000000 -0100
@@ -61,9 +61,11 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include <time.h>
 #include <openssl/ocsp.h>
 #include <openssl/err.h>
 #include <openssl/buffer.h>
+#include <openssl/bio.h>
 #ifdef OPENSSL_SYS_SUNOS
 #define strtoul (unsigned long)strtol
 #endif /* OPENSSL_SYS_SUNOS */
@@ -171,3 +173,176 @@
        BIO_free(mem);
        return resp;
 }
+OCSP_RESPONSE *OCSP_sendreq_bio_with_timeout(BIO *b, char *path, OCSP_REQUEST
+*req, long timeout)
+{
+       BIO *mem = NULL;
+       char tmpbuf[1024];
+       OCSP_RESPONSE *resp = NULL;
+       char *p, *q, *r,*buf=NULL;
+       int len=0, i ,retcode,offSet,socketDes;
+       fd_set rs,ws,wset,rset;
+       struct timeval tval, tmp;
+       static char req_txt[] =
+"POST %s HTTP/1.0\r\n\
+Content-Type: application/ocsp-request\r\n\
+Content-Length: %d\r\n\r\n";
+
+
+
+       if(!(mem = BIO_new(BIO_s_mem()))) goto err;
+
+       i = i2d_OCSP_REQUEST(req, NULL);
+       
+       if((len = BIO_printf(mem, req_txt, path, i)) < 0) goto err;
+       
+       if(i2d_OCSP_REQUEST_bio(mem, req) <= 0) goto err;
+       
+       len += i;
+
+       if(!(buf = (char *)OPENSSL_malloc(len))) goto err;
+       
+       len = BIO_read(mem,buf,len);
+       
+       BIO_free(mem);
+       
+       if(len <= 0)
+               goto err;
+
+       BIO_get_fd(b,&socketDes);
+
+       FD_ZERO(&wset);
+       FD_SET(socketDes,&wset);
+       FD_ZERO(&rset); 
+       
+
+       tval.tv_sec = timeout;
+       tval.tv_usec = 0;
+
+       if(!(mem = BIO_new(BIO_s_mem()))) goto err;
+       
+       offSet = 0;
+       while(1)
+       {
+               FD_ZERO(&rs);
+               FD_ZERO(&ws);
+               
+               rs = rset;
+               ws = wset;
+               
+               tmp = tval;
+               
+               if(select(socketDes+1,&rs,&ws,NULL,&tmp) == 0){
+                       
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_TIMEOUT_ERROR);
+                       goto err;
+               }
+               else
+               {
+                       if(FD_ISSET(socketDes,&rs) || FD_ISSET(socketDes,&ws)){
+                               retcode = BIO_sock_error(socketDes);
+                               if(retcode<0){
+                                       
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_CONNECT_ERROR);
+                                       goto err;       
+                               }
+                       }
+                       if(FD_ISSET(socketDes,&rs)){
+                               i = BIO_read(b, tmpbuf, sizeof tmpbuf);
+                               if(i == 0)      break;
+                               if(i < 0) {
+                                       if(!BIO_should_retry(b)){
+                                               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_READ_ERROR);
+                                               goto err;       
+                                       }
+                               
+                               }
+                               BIO_write(mem,tmpbuf,i);
+                       }
+                       if(FD_ISSET(socketDes,&ws)){
+                       
+                               if((i = BIO_write(b,buf+offSet,len)) <= 0){
+                                       if(!BIO_should_retry(b)){
+                                               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_WRITE_ERROR);
+                                               goto err;       
+                                       }
+                                               
+                               }
+                               offSet += i;
+                               len -= i;
+                               if(len <= 0){
+                                       FD_CLR(socketDes,&wset);
+                                       FD_SET(socketDes,&rset);
+                               }
+                       }
+               }
+       }
+
+       if(BIO_gets(mem, tmpbuf, 512) <= 0) {
+               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               goto err;
+       }
+       /* Parse the HTTP response. This will look like this:
+        * "HTTP/1.0 200 OK". We need to obtain the numeric code and
+         * (optional) informational message.
+        */
+
+       /* Skip to first white space (passed protocol info) */
+       for(p = tmpbuf; *p && !isspace((unsigned char)*p); p++) continue;
+       if(!*p) {
+               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               goto err;
+       }
+       /* Skip past white space to start of response code */
+       while(*p && isspace((unsigned char)*p)) p++;
+       if(!*p) {
+               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               goto err;
+       }
+       /* Find end of response code: first whitespace after start of code */
+       for(q = p; *q && !isspace((unsigned char)*q); q++) continue;
+       if(!*q) {
+               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               goto err;
+       }
+       /* Set end of response code and start of message */ 
+       *q++ = 0;
+       /* Attempt to parse numeric code */
+       retcode = strtoul(p, &r, 10);
+       if(*r) goto err;
+       /* Skip over any leading white space in message */
+       while(*q && isspace((unsigned char)*q))  q++;
+       if(*q) {
+       /* Finally zap any trailing white space in message (include CRLF) */
+       /* We know q has a non white space character so this is OK */
+               for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0;
+       }
+       if(retcode != 200) {
+               
OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_SERVER_RESPONSE_ERROR);
+               if(!*q) { 
+                       ERR_add_error_data(2, "Code=", p);
+               }
+               else {
+                       ERR_add_error_data(4, "Code=", p, ",Reason=", q);
+               }
+               goto err;
+       }
+       /* Find blank line marking beginning of content */      
+       while(BIO_gets(mem, tmpbuf, 512) > 0)
+       {
+               for(p = tmpbuf; *p && isspace((unsigned char)*p); p++) continue;
+               if(!*p) break;
+       }
+       if(*p) {
+               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,OCSP_R_NO_CONTENT);
+               goto err;
+       }
+       if(!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) {
+               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT,ERR_R_NESTED_ASN1_ERROR);
+               goto err;
+       }
+       err:
+       if(buf != NULL) OPENSSL_free(buf);
+       if(mem != NULL) BIO_free(mem);
+       return resp;
+}
+
+
diff -ur ./openssl-0.9.7d-orig/include/openssl/ocsp.h 
./openssl-0.9.7d/include/openssl/ocsp.h
--- ./openssl-0.9.7d-orig/include/openssl/ocsp.h        2004-04-19 18:19:23.210001000 
-0100
+++ ./openssl-0.9.7d/include/openssl/ocsp.h     2004-04-20 10:48:10.900002000 -0100
@@ -404,6 +404,8 @@
                (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
 
 OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_sendreq_bio_with_timeout(BIO *b, char *path, OCSP_REQUEST *req, 
long timeout);
+
 
 OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
 
@@ -579,6 +581,7 @@
 #define OCSP_F_OCSP_REQUEST_VERIFY                      116
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC                         111
 #define OCSP_F_OCSP_SENDREQ_BIO                                 112
+#define OCSP_F_OCSP_SENDREQ_BIO_WITH_TIMEOUT            117
 #define OCSP_F_REQUEST_VERIFY                           113
 
 /* Reason codes. */
@@ -612,6 +615,9 @@
 #define OCSP_R_UNKNOWN_MESSAGE_DIGEST                   119
 #define OCSP_R_UNKNOWN_NID                              120
 #define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE           129
+#define OCSP_R_SERVER_CONNECT_ERROR                     130
+#define OCSP_R_SERVER_TIMEOUT_ERROR                     131
+
 
 #ifdef  __cplusplus
 }

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature



Reply via email to