--- ./openca-ocspd-1.9.0/src/ocspd.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/ocspd.c 2011-06-17 17:29:04.000000000 +0200 @@ -64,6 +64,7 @@ " -md digest - Set digest to be used [md5]\n", " -k pwd - Password protecting the private key (if any)\n", " -i passin - Passin arg\n", +" -u baseuri - Base URI for GET requests (defaults to /)\n", #ifdef _OLD_HAVE_ENGINE " -e engine - use engine e, possibly a hardware device.\n", #endif @@ -116,6 +117,7 @@ char *pidfile = NULL; char *chroot_dir = NULL; char *tmp_s = NULL; + char *base_uri = "/"; // int keyform = FORMAT_PEM; /* ADD ENGINE SUPPORT */ @@ -201,6 +203,11 @@ debug=1; else if (strcmp(*argv,"-d") == 0) daemon=1; + else if (strcmp(*argv,"-u") == 0) + { + if (--argc < 1) goto bad; + base_uri = *(++argv); + } else badops = 1; argc--; argv++; @@ -262,6 +269,9 @@ /* Set the CRL checking variables */ ocspd_conf->crl_check_validity = 0; + /* set the base URI for GET requests */ + ocspd_conf->base_uri = base_uri; + /* ENGINE support added */ #ifdef HAVE_ENGINE /* Get db Filename */ --- ./openca-ocspd-1.9.0/src/crl.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/crl.c 2011-06-21 17:14:37.000000000 +0200 @@ -27,6 +27,9 @@ extern OCSPD_CONFIG * ocspd_conf; extern pthread_rwlock_t crl_lock; extern pthread_cond_t crl_cond; +extern ssize_t nr_of_requests; +extern ssize_t nr_of_replies; +extern ssize_t nr_of_errors; int ocspd_load_ca_crl ( CA_LIST_ENTRY *a ) { @@ -299,6 +302,9 @@ CA_LIST_ENTRY *ca = NULL; int i, ret; + syslog(LOG_INFO, "info: NREQ %ld NREP %ld NERR %ld", + nr_of_requests, nr_of_replies, nr_of_errors); + if( ocspd_conf->verbose == 1 ) { syslog(LOG_INFO, "INFO::auto_crl_check() started"); } --- ./openca-ocspd-1.9.0/src/configuration.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/configuration.c 2011-05-01 12:06:53.000000000 +0200 @@ -229,6 +229,8 @@ serv_cert_url = getParsedUrl( servUrl_s ); if( serv_cert_url != NULL ) { ca->ocsp_cert = ocspd_get_cert (serv_cert_url); + syslog(LOG_INFO, "Loaded OCSP Cert %s to %p", + servUrl_s, ca->ocsp_cert); URL_free( serv_cert_url ); } } --- ./openca-ocspd-1.9.0/src/hash-db.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/hash-db.c 2011-05-01 12:06:53.000000000 +0200 @@ -87,7 +87,7 @@ X509 *ret = NULL; STACK_OF(X509) *st = NULL; - if((st = ocspd_get_ca( url )) == NULL ) { + if((st = ocspd_get_ca( url )) != NULL ) { ret = sk_X509_value( st, 0); }; @@ -678,6 +678,7 @@ #endif STACK_OF(CA_ENTRY_CERTID) *cid_sk = NULL; X509 *x = NULL; + X509_ALGOR *algo; unsigned char buff[EVP_MAX_MD_SIZE]; @@ -728,10 +729,14 @@ return (NULL); }; cid->hashAlgorithm = (X509_ALGOR *) OBJ_nid2obj(nid); - if(cid->hashAlgorithm == NULL) { + algo = (X509_ALGOR *) OPENSSL_malloc ( sizeof(X509_ALGOR)); + if(cid->hashAlgorithm == NULL || algo == NULL) { + if( cid->hashAlgorithm ) X509_ALGOR_free( cid->hashAlgorithm); if( cid ) OPENSSL_free (cid); return (NULL); }; + memcpy(algo, cid->hashAlgorithm, sizeof(X509_ALGOR)); + cid->hashAlgorithm = algo; cid->hashAlgorithm->parameter = ASN1_TYPE_new(); if(cid->hashAlgorithm->parameter == NULL ) { if( cid->hashAlgorithm ) X509_ALGOR_free( cid->hashAlgorithm); --- ./openca-ocspd-1.9.0/src/ocsp_request.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/ocsp_request.c 2011-06-17 22:29:23.000000000 +0200 @@ -8,6 +8,7 @@ #include "threads.h" #include "sock.h" +#include "ocsp_http.h" #include "ocsp_request.h" #include "support.h" @@ -23,25 +24,17 @@ ssize_t fullsize = 0; ssize_t newsize = 0; ssize_t maxsize = 0; - ssize_t cont_len = 0; - ssize_t full_req_size = 0; char* buf = NULL; - int post = 0; - int headers = 0; int sel_ret = 0; - int cont = 0; - - char *pnt = NULL; - char *pnt_end = NULL; - char *req_st = NULL; - BIO *mem = NULL; OCSP_REQUEST * req = NULL; struct timeval time_out; fd_set readset; + http_rec_t *http_rec = NULL; + int error; if( !ocspd_conf ) { return (NULL); @@ -55,6 +48,8 @@ maxsize = OCSPD_DEF_MAX_SIZE - OCSPD_DEF_MAX_READ; } + error = 0; + /* Add the socket to the read set */ FD_ZERO( &readset ); FD_SET (connfd, &readset); @@ -68,12 +63,6 @@ return(NULL); } - cont = 0; - /* - while((sel_ret = Select(connfd+1, &readset, - NULL, NULL, &time_out)) >= 0) { - */ - full_req_size = 0; for(;;) { FD_ZERO( &readset ); @@ -119,12 +108,18 @@ } */ - // cont += WAIT_USEC; - if (FD_ISSET (connfd, &readset)) { + if(fullsize + OCSPD_DEF_MAX_READ >= maxsize) + { + syslog(LOG_ERR, "ERROR::NET::Socket recv buffer overflow"); + free(buf); + return(NULL); + } + if((newsize = recv(connfd, &(buf[fullsize]), OCSPD_DEF_MAX_READ, 0 )) == 0 ) { - break; + free(buf); + return(NULL); } if (newsize < 0) { @@ -137,7 +132,8 @@ continue; } } - break; + free(buf); + return(NULL); } if( ocspd_conf->debug ) { @@ -161,73 +157,59 @@ } */ - /* Check for headers */ - if( (!cont_len) && - ((pnt = strstr_nocase(buf, "Content-Length: " )) != NULL) ) { - if((pnt_end = strstr(pnt, "\r\n")) != NULL ) - sscanf((char *) (pnt+16), "%d", &cont_len ); - if(ocspd_conf->debug) { - syslog(LOG_ERR, "DEBUG::Got Content Len [%d]", - cont_len); - } - } - fullsize += newsize; - if( (!headers) && - (((pnt = strstr(buf, "\r\n\r\n")) != NULL) || - ((pnt = strstr(buf, "\n\n")) != NULL)) ) { - - while( (*pnt == '\n') || (*pnt == '\r')) { - *pnt = '\x0'; - pnt++; - } - - if( !cont_len ) { - if(ocspd_conf->verbose) - syslog(LOG_ERR, "ERROR::No " - "Content-Length" - " in REQ Headers"); - if(ocspd_conf->debug) { - fprintf( stderr,"---BEGIN HEADERS---\n" - "%s\n" - "---END HEADERS---\n\n", - buf ); - } - free(buf); - return(NULL); - } - req_st = pnt; - headers = (int) (req_st - buf); - full_req_size = headers+cont_len; - } - - if( (!post) && (fullsize >= 5 ) && - ( strncmp_nocase( buf, "POST ", 5) != 0 )) { - - /* Got an error - probably not found (?) */ - if( ocspd_conf->verbose) { - syslog( LOG_ERR, "ERROR::Request::HTTP method " - "is not POST"); - } - - free(buf); - return(NULL); - } - if( fullsize >= maxsize ) { /* Max Reading size exceeded */ - syslog( LOG_ERR, - "ERROR::Max REQUEST size exceeded [ %d ]", - maxsize ); - free( buf ); + syslog(LOG_ERR, "ERROR::Max REQUEST size " + "exceeded [ %d ]", maxsize); + free(buf); return(NULL); } - if( (full_req_size > 0) && - (full_req_size - fullsize < 1 )) { + http_rec = decode_http_request(buf, fullsize, &error); + + if(!http_rec) + { + switch(error) + { + case HTTP_CONTINUE: + continue; + case HTTP_HEADER_TRUNCATED: + syslog(LOG_ERR, "ERROR::HTTP Header truncated"); + free(buf); + return(NULL); + case HTTP_OVERFLOW: + syslog(LOG_ERR, "ERROR::HTTP overflow detected"); + free(buf); + return(NULL); + case HTTP_INVALID_CONTENTLEN: + syslog(LOG_ERR, "ERROR::HTTP::POST Invalid Content-Length"); + free(buf); + return(NULL); + case HTTP_ALLOC_ERROR: + syslog(LOG_ERR, "CRIT::Alloc Could not allocate memory!!"); + free(buf); + return(NULL); + case HTTP_BASEURI_ERROR: + syslog(LOG_ERR, "ERROR::HTTP::GET Invalid base URI!!"); + free(buf); + return(NULL); + case HTTP_URI_DECODE: + syslog(LOG_ERR, "ERROR::HTTP::GET Could not decode the base64 encoded URI"); + free(buf); + return(NULL); + case HTTP_BASE64_DECODE: + syslog(LOG_ERR, "ERROR::HTTP::GET Could not decode base64 URI"); + free(buf); + return(NULL); + case HTTP_INVALID_METHOD: + syslog(LOG_ERR, "ERROR::HTTP Invalid method in request"); + free(buf); + return(NULL); + } - break; } + break; } } @@ -239,7 +221,7 @@ buf ); } - if(!(mem = BIO_new_mem_buf(req_st, cont_len) )) { + if(!(mem = BIO_new_mem_buf(http_rec->http_data, http_rec->content_len) )) { BIO *err = NULL; if((err = BIO_new(BIO_s_file())) != NULL) { @@ -251,7 +233,7 @@ syslog( LOG_ERR, "ERROR: Internal memory allocation error!"); if(ocspd_conf->debug) { fprintf(stderr, "ERROR::req_st=%p [len %d]\n", - req_st, cont_len); + http_rec->http_data, http_rec->content_len); } } else { if((req = d2i_OCSP_REQUEST_bio(mem, NULL)) == NULL ) { @@ -261,10 +243,10 @@ fprintf(stderr, "[len %d] buf=%p -- req_st=%p " "(fullsize %d - hd_size = %d - " "rq_size = %d)\n", - cont_len, buf, - req_st, fullsize, - req_st - buf, - fullsize - (req_st - buf) ); + http_rec->content_len, buf, + http_rec->http_data, fullsize, + http_rec->http_data - buf, + fullsize - (http_rec->http_data - buf) ); } } if(mem) BIO_free (mem); @@ -272,6 +254,8 @@ if( buf ) free (buf); + if(http_rec) free_http_rec(http_rec); + return (req); } --- ./openca-ocspd-1.9.0/src/ocsp_response.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/ocsp_response.c 2012-02-15 15:41:02.000000000 +0100 @@ -29,6 +29,8 @@ OCSP_CERTID *cid = NULL; OCSP_BASICRESP *bs = NULL; OCSP_RESPONSE *resp = NULL; + CA_LIST_ENTRY *ca = NULL; + CA_LIST_ENTRY *firstca = NULL; int i, id_count; @@ -56,7 +58,6 @@ for (i = 0; i < id_count; i++) { OCSP_ONEREQ *one = NULL; ASN1_INTEGER *serial = NULL; - CA_LIST_ENTRY *ca = NULL; X509_REVOKED *entry = NULL; one = OCSP_request_onereq_get0(req, i); @@ -83,6 +84,16 @@ continue; } + /* In case of multiple requests, keep track of CA */ + if (firstca == NULL) { + firstca = ca; + } else { + if (firstca != ca) { + syslog(LOG_ERR, "ERROR, CA mismatch for id %d of %d: firstca = %p ca = %p [ignored]", + i, id_count, firstca, ca); + } + } + if( ca->compromised > 0 ) { OCSP_basic_add1_status( bs, cid, V_OCSP_CERTSTATUS_REVOKED, 0, NULL, @@ -159,8 +170,8 @@ } else { if( conf->verbose ) { - syslog( LOG_INFO, "status VALID for %ld", - ASN1_INTEGER_get(serial) ); + syslog( LOG_INFO, "status VALID for %ld, ca = %p", + ASN1_INTEGER_get(serial), ca ); } OCSP_basic_add1_status(bs, cid, @@ -173,6 +184,15 @@ /* It seems that this function is not thread safe!!! */ if ( pkey != NULL ) { + if ( firstca == NULL ) { + syslog(LOG_ERR, "[%s:%d] ERROR::FIRSTCA is NULL!", + __FILE__, __LINE__ ); + if ( resp ) OCSP_RESPONSE_free ( resp ); + resp = NULL; + + goto end; + } + if ( conf->ocspd_cert == 0 ) { syslog(LOG_ERR, "[%s:%d] ERROR::OCSP_CERT is NULL!", __FILE__, __LINE__ ); @@ -193,7 +213,12 @@ // pthread_mutex_lock ( &sign_mutex ); /* Sign the response only if we have a valid pkey pointer! */ - if(OCSP_basic_sign(bs, conf->ocspd_cert, pkey, + /* Assumptions are: + * - in a request with multiple cert ids, all refer to the same ca; + * - when multiple ca's are configured, they must all share the same pkey; + * so we can sign the reply with ca->ocsp_cert rather than conf->ocspd_cert! + */ + if(OCSP_basic_sign(bs, firstca->ocsp_cert, pkey, conf->digest, conf->other_certs, conf->flags) == 0 ) { syslog(LOG_ERR, "[Thread] ERROR::Response " "Signature Failed (OpenSSL Error is -> %s)", @@ -238,7 +263,6 @@ char http_resp[] = "HTTP/1.0 200 OK\r\n" "Content-type: application/ocsp-response\r\n" - "Content-Transfer-Encoding: Binary\r\n" "Content-Length: %d\r\n"; /* @@ -262,6 +286,7 @@ date = ASN1_GENERALIZEDTIME_new(); expire = ASN1_GENERALIZEDTIME_new(); + X509_gmtime_adj(date, 0); if( conf->set_nextUpdate ) { X509_gmtime_adj(expire, (conf->nmin * 60) + (conf->ndays * 60 * 60 * 24) ); --- ./openca-ocspd-1.9.0/src/threads.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/threads.c 2011-06-21 17:23:53.000000000 +0200 @@ -21,7 +21,11 @@ extern pthread_mutex_t crl_mutex; +extern ssize_t nr_of_replies; +extern ssize_t nr_of_errors; + pthread_mutex_t resp_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t err_mutex = PTHREAD_MUTEX_INITIALIZER; int thread_make ( int i ) { Thread *th_ptr = NULL; @@ -196,7 +200,9 @@ if((req = ocspd_req_get_socket(connfd, ocspd_conf)) == NULL ) { - syslog(LOG_ERR, "ERROR::Can not parse REQ"); + if( ocspd_conf->debug) { + syslog(LOG_ERR, "ERROR::Can not parse REQ"); + } goto err; } @@ -219,6 +225,10 @@ goto end; err: + pthread_mutex_lock( &err_mutex ); + nr_of_errors++; + pthread_mutex_unlock( &err_mutex ); + if( ocspd_conf->debug) { syslog(LOG_ERR, "[Thread::%d] - An error occurred!", thread_nr); @@ -244,6 +254,7 @@ ocspd_resp_send_socket( connfd, resp, ocspd_conf ); pthread_mutex_lock( &resp_mutex ); + nr_of_replies++; if( resp ) { OCSP_RESPONSE_free (resp); resp = NULL; --- ./openca-ocspd-1.9.0/src/core.c.org 2009-06-08 19:24:05.000000000 +0200 +++ ./openca-ocspd-1.9.0/src/core.c 2011-06-21 17:13:39.000000000 +0200 @@ -22,6 +22,10 @@ extern void auto_crl_check( int ); extern OCSPD_CONFIG *ocspd_conf; +ssize_t nr_of_requests = 0; +ssize_t nr_of_replies = 0; +ssize_t nr_of_errors = 0; + pthread_rwlock_t crl_lock = PTHREAD_RWLOCK_INITIALIZER; /* pthread_cond_t crl_cond; */ @@ -140,6 +144,7 @@ strerror(errno)); exit(-1); } + nr_of_requests++; if( ocspd_conf->verbose ) syslog( LOG_INFO, "INFO::CORE::Connection from [%s]\n", inet_ntoa(cliaddr.sin_addr) ); @@ -290,6 +295,8 @@ } void close_server ( void ) { + syslog(LOG_INFO, "info: NREQ %ld NREP %ld NERR %ld", + nr_of_requests, nr_of_replies, nr_of_errors); syslog( LOG_ERR, "Exiting, Glad to serve you, Master!"); return;