Some openca-ocspd patches.

View: New views
4 Messages — Rating Filter:   Alert me  

Some openca-ocspd patches.

by Mark Ellzey Thomas :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Greetings OpenCA developers!

We have recently been looking into utilizing the OpenCA ocsp daemon for
our own CA and have found it most useful.

We did run into some issues with both bugs and features.

After running the daemon under a small bit of load we found that the
daemon would crash at random intervals - after a quick glance at the
source it seems that OpenSSL was not being initialized in a thread safe
manner. This fix is included within the patch.

We also needed the ability for the code to handle GET style methods for
ocsp requests. After looking over the current http handling code it was
determined that cleaning up and re-factoring the http processing
functionality may be in order. This was also included within the patch.

In order to facilitate the GET requests I had to add a new flag "-u"
where an administrator can specify the root URI (e.g., -u /ocsp/) so the
code knows to read the encoded data found afterwards.  

I hope that you find these changes useful, and I thank you for the great
project!

~Mark

diff -Naur ../openca-ocspd-1.5.1-rc1/src/Makefile.in ./src/Makefile.in
--- ../openca-ocspd-1.5.1-rc1/src/Makefile.in 2006-10-14 10:34:53.000000000 -0400
+++ ./src/Makefile.in 2009-06-05 16:03:44.000000000 -0400
@@ -63,9 +63,9 @@
  configuration.c configuration.h crl.h crl.c support.c \
  support.h crypto.c crypto.h http_client.c http_client.h core.h \
  threads.h sock.h structs.h core.c sock.c threads.c ocsp_db.h \
- hash-db.c ocspd_engine.c ocspd_engine.h
+ hash-db.c ocspd_engine.c ocspd_engine.h ocsp_http.c ocsp_http.h
 @HAVE_ENGINE_TRUE@am__objects_1 = ocspd_engine.$(OBJEXT)
-am_ocspd_OBJECTS = ocspd.$(OBJEXT) ocsp_response.$(OBJEXT) \
+am_ocspd_OBJECTS = ocspd.$(OBJEXT) ocsp_http.$(OBJEXT) ocsp_response.$(OBJEXT) \
  ocsp_request.$(OBJEXT) configuration.$(OBJEXT) crl.$(OBJEXT) \
  support.$(OBJEXT) crypto.$(OBJEXT) http_client.$(OBJEXT) \
  core.$(OBJEXT) sock.$(OBJEXT) threads.$(OBJEXT) \
@@ -288,6 +288,7 @@
 #
 ocspd_SOURCES = \
  ocspd.c ocspd.h general.h ocsp_codes.h \
+  ocsp_http.c ocsp_http.h \
  ocsp_response.c ocsp_response.h \
  ocsp_request.c ocsp_request.h \
  configuration.c configuration.h \
@@ -402,6 +403,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash-db.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_client.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_request.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_http.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocspd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocspd_engine.Po@am__quote@
diff -Naur ../openca-ocspd-1.5.1-rc1/src/core.c ./src/core.c
--- ../openca-ocspd-1.5.1-rc1/src/core.c 2006-10-21 10:50:32.000000000 -0400
+++ ./src/core.c 2009-06-05 16:03:44.000000000 -0400
@@ -13,10 +13,20 @@
 extern OCSPD_CONFIG *ocspd_conf;
 
 pthread_mutex_t crl_lock = PTHREAD_MUTEX_INITIALIZER;
-
 pthread_mutex_t clifd_mutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_cond_t clifd_cond;
+pthread_mutex_t *thread_locks;
+
+unsigned long openssl_thread_id() {
+     return (unsigned long) pthread_self();
+}
 
+void openssl_thread_lock( int mode, int lock_id, const char* file, int line ) {
+    if ( mode & CRYPTO_LOCK )
+ pthread_mutex_lock( &thread_locks[lock_id] );
+    else
+ pthread_mutex_unlock( &thread_locks[lock_id] );
+}
 
 int start_threaded_server ( char * bind_s, char * port_s, int nthreads,
  OCSPD_CONFIG * ocspd_conf ) {
@@ -77,6 +87,23 @@
 
  ocspd_conf->iget = ocspd_conf->iput = 0;
 
+ int num_thread_locks = CRYPTO_num_locks();
+ thread_locks = calloc( sizeof( pthread_mutex_t ),
+ num_thread_locks );
+
+ for (i = 0; i < num_thread_locks; i++)
+ {
+    if ( pthread_mutex_init( &thread_locks[i], NULL ) )
+    {
+ fprintf(stderr, "Unable to create mutex\n");
+ exit(80);
+    }
+ }
+
+ CRYPTO_set_locking_callback( &openssl_thread_lock );
+        CRYPTO_set_id_callback( &openssl_thread_id );
+
+
  for( i = 0; i < ocspd_conf->nthreads; i++ ) {
  if(thread_make(i) != 0 ) {
  syslog(LOG_ERR,
@@ -86,6 +113,7 @@
  }
  }
 
+
  /* Register the alarm handler */
  set_alrm_handler();
 
@@ -178,6 +206,8 @@
  return 1;
 }
 
+
+
 void handle_sighup ( int i ) {
 
  syslog( LOG_ERR,
diff -Naur ../openca-ocspd-1.5.1-rc1/src/general.h ./src/general.h
--- ../openca-ocspd-1.5.1-rc1/src/general.h 2006-10-21 08:53:55.000000000 -0400
+++ ./src/general.h 2009-06-05 16:03:44.000000000 -0400
@@ -381,6 +381,7 @@
  STACK *pre_cmds;
  STACK *post_cmds;
 #endif
+ char *base_uri;
 } OCSPD_CONFIG;
 
 #define CRL_REASON_UNSPECIFIED 0
diff -Naur ../openca-ocspd-1.5.1-rc1/src/ocsp_http.c ./src/ocsp_http.c
--- ../openca-ocspd-1.5.1-rc1/src/ocsp_http.c 1969-12-31 19:00:00.000000000 -0500
+++ ./src/ocsp_http.c 2009-06-08 12:13:43.000000000 -0400
@@ -0,0 +1,573 @@
+#include <strings.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include "core.h"
+#include "threads.h"
+#include "sock.h"
+
+#include "ocsp_request.h"
+#include "ocsp_http.h"
+
+extern OCSPD_CONFIG *ocspd_conf;
+
+http_method_t
+decode_http_method(const char *str, int len, int *error)
+{
+    http_method_t   method;
+
+    switch (*str) {
+    case 'p':
+    case 'P':
+        if (len < 5) {
+            *error = HTTP_HEADER_TRUNCATED;
+            return METHOD_ERROR;
+        }
+
+        if (strncasecmp(str, "POST ", 5)) {
+            *error = HTTP_INVALID_METHOD;
+            return METHOD_ERROR;
+        }
+
+        method = METHOD_POST;
+        break;
+    case 'g':
+    case 'G':
+        if (len < 4) {
+            *error = HTTP_HEADER_TRUNCATED;
+            return METHOD_ERROR;
+        }
+
+        if (strncasecmp(str, "GET ", 4)) {
+            *error = HTTP_INVALID_METHOD;
+            return METHOD_ERROR;
+        }
+
+        method = METHOD_GET;
+        break;
+    default:
+        *error = HTTP_INVALID_METHOD;
+        return METHOD_ERROR;
+    }
+
+    return method;
+}
+
+char           *
+http_expand_hex(const char *hexstr)
+{
+    switch (strtol(hexstr, NULL, 16)) {
+    case 0x24:
+        return "$";
+    case 0x26:
+        return "&";
+    case 0x2B:
+        return "+";
+    case 0x2C:
+        return ",";
+    case 0x2F:
+        return "/";
+    case 0x3A:
+        return ":";
+    case 0x3B:
+        return ";";
+    case 0x3D:
+        return "=";
+    case 0x3F:
+        return "?";
+    case 0x40:
+        return "@";
+    case 0x20:
+        return " ";
+    case 0x22:
+        return "\"";
+    case 0x3C:
+        return "<";
+    case 0x3E:
+        return ">";
+    case 0x23:
+        return "#";
+    case 0x25:
+        return "%";
+    case 0x7b:
+        return "{";
+    case 0x7d:
+        return "}";
+    case 0x7c:
+        return "|";
+    case 0x5c:
+        return "\\";
+    case 0x5e:
+        return "^";
+    case 0x7e:
+        return "~";
+    case 0x5B:
+        return "[";
+    case 0x5D:
+        return "]";
+    case 0x60:
+        return "`";
+    default:
+        return NULL;
+    }
+    return NULL;
+}
+
+char           *
+http_decode_base64(char *input, int len, int *tlen)
+{
+    BIO            *bio,
+                   *b64;
+    char           *outbuf;
+    int             inlen;
+
+    if (!(outbuf = malloc(4096))) {
+        *tlen = -1;
+        return NULL;
+    }
+
+    memset(outbuf, 0, 4096);
+
+    b64 = BIO_new(BIO_f_base64());
+    bio = BIO_new_mem_buf(input, len);
+    bio = BIO_push(b64, bio);
+
+    while ((inlen = BIO_read(bio, outbuf, 4096)) > 0)
+        *tlen += inlen;
+
+    BIO_free_all(bio);
+
+    return outbuf;
+}
+
+char           *
+decode_uri(char *in_uri, int len)
+{
+    int             i;
+    int             current_byte;
+    int             characters_written;
+    int             outstring_len;
+    char           *outstring;
+
+    if (!in_uri || len <= 0)
+        return NULL;
+
+    /*
+     * (len / 64) is the number of newline characters that will need to
+     * be added.
+     *
+     * We also add 2 more bytes to the end for the last \n, and a \0
+     * terminator.
+     */
+
+    outstring_len = (len / 64) + len + 2;
+    characters_written = 0;
+
+    if (!(outstring = malloc(outstring_len)))
+        return NULL;
+
+    memset(outstring, 0, outstring_len);
+
+    current_byte = 0;
+
+    for (i = 0; i < len; i++) {
+        char           *data;
+        char           *hexstr;
+        char           *expanded;
+
+        data = &in_uri[i];
+
+        /*
+         * openssl base64 decoding requires our encoded string to include
+         * newlines after every 64 bytes
+         */
+        if (i > 0 && !(characters_written % 63)) {
+            outstring[current_byte++] = '\n';
+        }
+
+        if (*data != '%') {
+            outstring[current_byte++] = *data;
+            characters_written++;
+            continue;
+        }
+
+        if (i + 2 >= outstring_len) {
+            /*
+             * we can't actually fit a hex set here
+             */
+            outstring[current_byte++] = *data;
+            characters_written++;
+            continue;
+        }
+
+        hexstr = malloc(3);
+        hexstr[0] = data[1];
+        hexstr[1] = data[2];
+        hexstr[2] = '\0';
+
+        expanded = http_expand_hex(hexstr);
+
+        if (expanded) {
+            outstring[current_byte++] = *expanded;
+            i += 2;
+        } else
+            outstring[current_byte++] = *data;
+
+        characters_written++;
+        free(hexstr);
+    }
+
+    outstring[current_byte] = '\n';
+
+    return outstring;
+}
+
+http_rec_t     *
+create_http_rec(void)
+{
+    http_rec_t     *rec;
+
+    if (!(rec = malloc(sizeof(http_rec_t))))
+        return NULL;
+
+    memset(rec, 0, sizeof(http_rec_t));
+    return rec;
+}
+
+void
+free_http_rec(http_rec_t * rec)
+{
+    if (!rec)
+        return;
+
+    if (rec->http_raw_rec)
+        free(rec->http_raw_rec);
+
+    if (rec->http_data)
+        free(rec->http_data);
+
+    free(rec);
+}
+
+int
+decode_http_content_len(char *input_buf, int input_len)
+{
+    /*
+     * return values: -1 error occurred 0 not enough data >0 the length to
+     * read
+     */
+    char           *content_sz_raw;
+    char           *content_sz_val_raw;
+    char           *content_sz_val;
+    char           *content_sz_end;
+    int             content_sz_val_len;
+    int             content_len;
+
+    /*
+     * first find the content-length header
+     */
+    content_sz_raw = strstr(input_buf, "Content-Length: ");
+
+    if (!content_sz_raw)
+        return 0;
+
+    /*
+     * paranoid overflow check
+     */
+    if (content_sz_raw > (char *) (input_buf + input_len))
+        return 0;
+
+    content_sz_val_raw = &content_sz_raw[16];
+
+    if (!content_sz_val_raw)
+        return 0;
+
+    if (content_sz_val_raw > (char *) (input_buf + input_len))
+        return 0;
+
+    /*
+     * find the end of the content-length line
+     */
+    content_sz_end = strstr(content_sz_val_raw, "\r\n");
+
+    if (!content_sz_end)
+        return 0;
+
+    /*
+     * get a general number of bytes to alloc
+     */
+    content_sz_val_len = content_sz_end - content_sz_val_raw;
+
+    if (content_sz_val_len <= 0)
+        return -1;
+
+    if (!(content_sz_val = malloc(content_sz_val_len)))
+        return -1;
+
+    memset(content_sz_val, 0, content_sz_val_len + 1);
+    strncpy(content_sz_val, content_sz_val_raw, content_sz_val_len);
+
+    content_len = atoi(content_sz_val);
+
+    free(content_sz_val);
+
+    if (content_len >= INT_LEAST32_MAX)
+        return -1;
+
+    return content_len;
+}
+
+char           *
+decode_http_post_data(char *input_buf, int input_len,
+                      int content_len, int *error)
+{
+    char           *headers_end;
+    char           *payload_start;
+    char           *input_buf_end;
+    int             current_content_len;
+
+
+    input_buf_end = (char *) (input_buf + input_len);
+
+    /*
+     * find the end of all the headers
+     */
+    headers_end = strstr(input_buf, "\r\n\r\n");
+
+    if (!headers_end)
+        headers_end = strstr(input_buf, "\n\n");
+
+    if (!headers_end) {
+        /*
+         * not enough data? continue on
+         */
+        *error = HTTP_CONTINUE;
+        return NULL;
+    }
+
+    payload_start = headers_end;
+
+    while ((*payload_start == '\n') || (*payload_start == '\r')) {
+        if (payload_start > input_buf_end)
+            break;
+
+        payload_start++;
+    }
+
+    if (payload_start > input_buf_end) {
+        *error = HTTP_OVERFLOW;
+        return NULL;
+    }
+
+    /*
+     * check to see if we have the entire payload as determined by the
+     * content_len
+     */
+    current_content_len = input_buf_end - payload_start;
+
+    if (current_content_len < content_len) {
+        *error = HTTP_CONTINUE;
+        return NULL;
+    }
+
+    if (current_content_len > content_len) {
+        *error = HTTP_OVERFLOW;
+        return NULL;
+    }
+
+    return payload_start;
+}
+
+
+http_rec_t     *
+decode_http_post(char *input_buf, int input_len, int *error)
+{
+    int             content_len;
+    char           *post_data;
+    http_rec_t     *rec;
+
+    content_len = decode_http_content_len(input_buf, input_len);
+
+    if (content_len == 0) {
+        *error = HTTP_CONTINUE;
+        return NULL;
+    }
+
+    if (content_len < 0) {
+        *error = HTTP_INVALID_CONTENTLEN;
+        return NULL;
+    }
+
+    post_data = decode_http_post_data(input_buf,
+                                      input_len, content_len, error);
+
+    if (!post_data)
+        return NULL;
+
+    if (!(rec = create_http_rec())) {
+        *error = HTTP_ALLOC_ERROR;
+        return NULL;
+    }
+
+    rec->method = METHOD_POST;
+    rec->request_len = input_len;
+    rec->content_len = content_len;
+
+    rec->http_raw_rec = malloc(input_len);
+    memcpy(rec->http_raw_rec, input_buf, input_len);
+
+    rec->http_data = malloc(content_len);
+    memcpy(rec->http_data, post_data, content_len);
+
+    return rec;
+}
+
+http_rec_t     *
+decode_http_get(char *input_buf, int input_len, int *error)
+{
+    /*
+     * decoding a ocsp GET request is a trivial task. Simply read the
+     * URI, hop past the base_uri, swap reserved characters with the real
+     * values, and base64 decode the string
+     */
+    http_rec_t     *rec;
+    char           *uri_start;
+    char           *uri_end;
+    char           *uri;
+    char           *decoded_uri;
+    char           *unbased_uri;
+    int             uri_len;
+    int             tlen;
+
+    rec = NULL;
+    tlen = 0;
+
+    /*
+     * lets first find the base URI
+     */
+    uri_start = strstr(input_buf, ocspd_conf->base_uri);
+
+    if (!uri_start) {
+        *error = HTTP_BASEURI_ERROR;
+        return NULL;
+    }
+
+    if (uri_start > (input_buf + input_len)) {
+        *error = HTTP_OVERFLOW;
+        return NULL;
+    }
+
+    /*
+     * increment past the base_uri
+     */
+    uri_start += strlen(ocspd_conf->base_uri);
+
+    /*
+     * find the end of the GET request by looking for the protocol
+     */
+    uri_end = strstr(uri_start, " HTTP/1");
+
+    if (!uri_end) {
+        *error = HTTP_HEADER_TRUNCATED;
+        return NULL;
+    }
+
+    if (uri_end > (input_buf + input_len)) {
+        *error = HTTP_OVERFLOW;
+        return NULL;
+    }
+
+    uri_len = uri_end - uri_start;
+
+    if (!(uri = malloc(uri_len + 1))) {
+        *error = HTTP_ALLOC_ERROR;
+        return NULL;
+    }
+
+    memset(uri, 0, uri_len + 1);
+    memcpy(uri, uri_start, uri_len);
+
+    /*
+     * do our reserved hex encoded swapping with the real thing
+     */
+    decoded_uri = decode_uri(uri, uri_len);
+    free(uri);
+
+    if (!decoded_uri) {
+        *error = HTTP_URI_DECODE;
+        return NULL;
+    }
+
+    /*
+     * now take the input uri and base64 decode
+     */
+    unbased_uri = http_decode_base64(decoded_uri,
+                                     strlen(decoded_uri), &tlen);
+
+    if (!unbased_uri || tlen <= 0) {
+        *error = HTTP_BASE64_DECODE;
+
+#if 0
+        printf("DECODED %p tlen %d\n", unbased_uri, tlen);
+
+        printf("IN BASE64\n=================\n%s\n=================\n",
+               decoded_uri);
+#endif
+
+        if (unbased_uri)
+            free(unbased_uri);
+
+        if (decoded_uri)
+            free(decoded_uri);
+
+        return NULL;
+    }
+
+    if (!(rec = create_http_rec())) {
+        if (decoded_uri)
+            free(decoded_uri);
+
+        if (unbased_uri)
+            free(unbased_uri);
+
+        *error = HTTP_HEADER_TRUNCATED;
+        return NULL;
+    }
+
+    rec->method = METHOD_GET;
+    rec->request_len = input_len;
+    rec->content_len = tlen;
+    rec->http_raw_rec = strdup(input_buf);
+    rec->http_data = unbased_uri;
+
+    if (decoded_uri)
+        free(decoded_uri);
+
+    return rec;
+}
+
+http_rec_t     *
+decode_http_request(char *input_buf, int input_len, int *error)
+{
+    http_method_t   method;
+    http_rec_t     *rec;
+
+    rec = NULL;
+
+    method = decode_http_method(input_buf, input_len, error);
+
+    switch (method) {
+    case METHOD_POST:
+        rec = decode_http_post(input_buf, input_len, error);
+        break;
+    case METHOD_GET:
+        rec = decode_http_get(input_buf, input_len, error);
+        break;
+    default:
+        return NULL;
+    }
+
+    return rec;
+}
diff -Naur ../openca-ocspd-1.5.1-rc1/src/ocsp_http.h ./src/ocsp_http.h
--- ../openca-ocspd-1.5.1-rc1/src/ocsp_http.h 1969-12-31 19:00:00.000000000 -0500
+++ ./src/ocsp_http.h 2009-06-05 16:03:44.000000000 -0400
@@ -0,0 +1,40 @@
+#ifndef __OCSP_HTTP_H
+#define __OCSP_HTTP_H
+
+#define HTTP_CONTINUE 0
+#define HTTP_HEADER_TRUNCATED -1
+#define HTTP_OVERFLOW -2
+#define HTTP_INVALID_CONTENTLEN -3
+#define HTTP_ALLOC_ERROR -4
+#define HTTP_BASEURI_ERROR -5
+#define HTTP_URI_DECODE -6
+#define HTTP_BASE64_DECODE -7
+#define HTTP_INVALID_METHOD -8
+
+typedef enum http_method {
+    METHOD_POST,
+    METHOD_GET,
+    METHOD_ERROR
+} http_method_t;
+
+typedef struct http_rec {
+    http_method_t method;
+    int request_len;
+    int content_len;
+
+    char *http_raw_rec;
+    char *http_data;
+} http_rec_t;
+
+http_method_t decode_http_method(const char *, int, int *);
+char *http_expand_hex(const char *);
+char *http_decode_base64(char *input, int len, int *tlen);
+char *http_decode_uri(char *in_uri, int len);
+http_rec_t *create_http_rec(void);
+void free_http_rec(http_rec_t *rec);
+int decode_http_content_len(char *input_buf, int input_len);
+char *decode_http_post_data(char *input_buf, int input_len, int content_len, int *error);
+http_rec_t *decode_http_post (char *input_buf, int input_len, int *error);
+http_rec_t *decode_http_get (char *input_buf, int input_len, int *error);
+http_rec_t *decode_http_request(char *input_buf, int input_len, int *error);
+#endif
diff -Naur ../openca-ocspd-1.5.1-rc1/src/ocsp_request.c ./src/ocsp_request.c
--- ../openca-ocspd-1.5.1-rc1/src/ocsp_request.c 2006-10-21 12:39:24.000000000 -0400
+++ ./src/ocsp_request.c 2009-06-05 16:03:44.000000000 -0400
@@ -8,6 +8,7 @@
 #include "threads.h"
 #include "sock.h"
 
+#include "ocsp_http.h"
 #include "ocsp_request.h"
 
 #define  OCSPD_DEF_MAX_SIZE 65535
@@ -18,29 +19,17 @@
 extern OCSPD_CONFIG *ocspd_conf;
 
 OCSP_REQUEST * ocspd_req_get_socket ( int connfd, OCSPD_CONFIG *ocspd_conf) {
-
  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);
@@ -54,6 +43,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);
@@ -67,14 +58,7 @@
  return(NULL);
  }
 
- cont = 0;
- /*
- while((sel_ret = Select(connfd+1, &readset,
- NULL, NULL, &time_out)) >= 0) {
- */
- full_req_size = 0;
  for(;;) {
-
  FD_ZERO( &readset );
  FD_SET (connfd, &readset);
 
@@ -106,21 +90,15 @@
  return(NULL);
  }
 
- /*
- if( ocspd_conf->debug ) {
- syslog(LOG_ERR, "DEBUG::NETWORK::Select "
- "%d (cont = %d)!", sel_ret, cont);
- }
-
- if( ocspd_conf->debug ) {
- syslog(LOG_ERR, "DEBUG::NETWORK::FD_ISSET "
- "%d", FD_ISSET(connfd, &readset) );
- }
- */
-
- // 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;
@@ -139,106 +117,78 @@
  break;
  }
 
+
  if( ocspd_conf->debug ) {
  syslog(LOG_ERR, "DEBUG::NETWORK::recv "
  "received %d (conn = %d)!", newsize, connfd);
  }
-
- /*
- if( sel_ret == 0 ) {
- if( (cont/1000) >= ocspd_conf->max_timeout_secs ) {
- if( ocspd_conf->verbose ) {
- syslog(LOG_ERR, "ERROR::NETWORK::Timeout "
- "reached while reading REQUEST (%d >= %d)!",
- cont/1000, ocspd_conf->max_timeout_secs);
- }
-
- break;
- } else {
- continue;
- }
- }
- */
-
- /* Check for headers */
- if( (!cont_len) &&
- ((pnt = strstr(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( 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 );
- return(NULL);
- }
-
- if( (full_req_size > 0) &&
- (full_req_size - fullsize < 1 )) {
-
- break;
+                        if( fullsize >= maxsize ) {
+                                /* Max Reading size exceeded */
+                                syslog( LOG_ERR,
+                                        "ERROR::Max REQUEST size exceeded [ %d ]",
+                                                maxsize );
+                                free( buf );
+                                return(NULL);
+                        }
+
+ 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;
  }
  }
 
- if(ocspd_conf->debug) {
- fprintf( stderr,"---BEGIN HEADERS---\n"
- "%s\n"
- "---END HEADERS---\n\n",
- 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) {
@@ -247,10 +197,10 @@
  BIO_free(err);
  }
 
-                syslog( LOG_ERR, "ERROR: Internal memory allocation error!");
+                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 ) {
@@ -260,16 +210,19 @@
  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);
  }
 
- if( buf ) free (buf);
+ if(buf)
+    free (buf);
+
+ free_http_rec(http_rec);
 
  return (req);
 }
diff -Naur ../openca-ocspd-1.5.1-rc1/src/ocspd.c ./src/ocspd.c
--- ../openca-ocspd-1.5.1-rc1/src/ocspd.c 2006-10-21 08:58:10.000000000 -0400
+++ ./src/ocspd.c 2009-06-05 16:03:44.000000000 -0400
@@ -63,6 +63,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
@@ -113,6 +114,7 @@
  char *pidfile = NULL;
  char *chroot_dir = NULL;
  char *tmp_s = NULL;
+ char *base_uri = "/";
  int keyform = FORMAT_PEM;
 
         /* ADD ENGINE SUPPORT */
@@ -195,6 +197,12 @@
  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++;
@@ -255,6 +263,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

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
OpenCA-Devel mailing list
OpenCA-Devel@...
https://lists.sourceforge.net/lists/listinfo/openca-devel

Re: Some openca-ocspd patches.

by Massimiliano Pala-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello Mark,

thanks for the patches :D They are definitely useful.. I will integrate
them soon.. I know the problem with the OpenSSL - but as we are planning
on using LibPKI (that allows for direct integration with easy integration
with PKCS#11 devices, among other things.. ) I was thinking about delaying
the release of the new code a bit.

I will probably check the patch and schedule for a new OCSP release quite
soon (before porting the server under LibPKI).

Thanks again :D

Ciao,
Max


Mark Ellzey Thomas wrote:

> Greetings OpenCA developers!
>
> We have recently been looking into utilizing the OpenCA ocsp daemon for
> our own CA and have found it most useful.
>
> We did run into some issues with both bugs and features.
>
> After running the daemon under a small bit of load we found that the
> daemon would crash at random intervals - after a quick glance at the
> source it seems that OpenSSL was not being initialized in a thread safe
> manner. This fix is included within the patch.
>
> We also needed the ability for the code to handle GET style methods for
> ocsp requests. After looking over the current http handling code it was
> determined that cleaning up and re-factoring the http processing
> functionality may be in order. This was also included within the patch.
>
> In order to facilitate the GET requests I had to add a new flag "-u"
> where an administrator can specify the root URI (e.g., -u /ocsp/) so the
> code knows to read the encoded data found afterwards.  
>
> I hope that you find these changes useful, and I thank you for the great
> project!
>
> ~Mark


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
OpenCA-Devel mailing list
OpenCA-Devel@...
https://lists.sourceforge.net/lists/listinfo/openca-devel

smime.p7s (4K) Download Attachment

Parent Message unknown Re: Some openca-ocspd patches.

by ajaybatheja :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Max,
        I tested the latest code given by Mark and it works great. Just a FYI, Get requests are ecoded slashes for e.g.:-
 
194.186.53.31 - - [08/Jun/2009:13:41:07 -0400] "GET
/ocsp/MEUwQzBBMD8wPTAJBgUrDgMCGgUABBTlXreDlf9xPB%2F%2BlgIfsGHd3PkLhgQUYaaZbSSfDh
GI5jng%2FnTRBWlSqUMCBHAABjw%3D HTTP/1.1" 200 2389 0 "-" "Microsoft-CryptoAPI/6.0"
 
Please update the documentation to configure apache, add the following information in httpd.conf otherwise apache webserver will get a 404 error:-
 
AllowEncodedSlashes On
  ProxyRequests Off
  ProxyPass /ocsp
http://localhost:2560/ocsp nocanon
  ProxyPassReverse /ocsp
http://localhost:2560/ocsp/ nocanon
 
Thanks
Ajay
 
In a message dated 6/8/2009 12:43:40 Eastern Daylight Time, Massimiliano.Pala@... writes:
Hello Mark,

thanks for the patches :D They are definitely useful.. I will integrate
them soon.. I know the problem with the OpenSSL - but as we are planning
on using LibPKI (that allows for direct integration with easy integration
with PKCS#11 devices, among other things.. ) I was thinking about delaying
the release of the new code a bit.

I will probably check the patch and schedule for a new OCSP release quite
soon (before porting the server under LibPKI).

Thanks again :D

Ciao,
Max


Mark Ellzey Thomas wrote:

> Greetings OpenCA developers!
>
> We have recently been looking into utilizing the OpenCA ocsp daemon for
> our own CA and have found it most useful.
>
> We did run into some issues with both bugs and features.
>
> After running the daemon under a small bit of load we found that the
> daemon would crash at random intervals - after a quick glance at the
> source it seems that OpenSSL was not being initialized in a thread safe
> manner. This fix is included within the patch.
>
> We also needed the ability for the code to handle GET style methods for
> ocsp requests. After looking over the current http handling code it was
> determined that cleaning up and re-factoring the http processing
> functionality may be in order. This was also included within the patch.
>
> In order to facilitate the GET requests I had to add a new flag "-u"
> where an administrator can specify the root URI (e.g., -u /ocsp/) so the
> code knows to read the encoded data found afterwards. 
>
> I hope that you find these changes useful, and I thank you for the great
> project!
>
> ~Mark


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects

_______________________________________________
OpenCA-Devel mailing list
OpenCA-Devel@...
https://lists.sourceforge.net/lists/listinfo/openca-devel

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
OpenCA-Devel mailing list
OpenCA-Devel@...
https://lists.sourceforge.net/lists/listinfo/openca-devel

Re: Some openca-ocspd patches.

by Massimiliano Pala-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I just finished "porting" the OCSP daemon to LibPKI. I have a problem with
Firefox - it crashes although the responses are perfectly compliant with
the RFC.. still investigating.

Anyhow, I am now adding support for GET requests... work in progress...

Later,
Max


Akbatheja@... wrote:

> Max,
>         I tested the latest code given by Mark and it works great. Just
> a FYI, Get requests are ecoded slashes for e.g.:-
>  
> 194.186.53.31 - - [08/Jun/2009:13:41:07 -0400] "GET
> /ocsp/MEUwQzBBMD8wPTAJBgUrDgMCGgUABBTlXreDlf9xPB%2F%2BlgIfsGHd3PkLhgQUYaaZbSSfDh
> GI5jng%2FnTRBWlSqUMCBHAABjw%3D HTTP/1.1" 200 2389 0 "-"
> "Microsoft-CryptoAPI/6.0"
>  
> Please update the documentation to configure apache, add the following
> information in httpd.conf otherwise apache webserver will get a 404 error:-
>  
> *AllowEncodedSlashes On
>   ProxyRequests Off
>   ProxyPass /ocsp **http://localhost:2560/ocsp** nocanon
>   ProxyPassReverse /ocsp **http://localhost:2560/ocsp/** nocanon*
> **
> Thanks
> Ajay
--

Best Regards,

        Massimiliano Pala

--o------------------------------------------------------------------------
Massimiliano Pala [OpenCA Project Manager]                   openca@...
                                                  project.manager@...

Dartmouth Computer Science Dept               Home Phone: +1 (603) 369-9332
PKI/Trust Laboratory                          Work Phone: +1 (603) 646-8734
--o------------------------------------------------------------------------
People who think they know everything are a great annoyance to those of us
who do.
                                                           -- Isaac Asimov


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
OpenCA-Devel mailing list
OpenCA-Devel@...
https://lists.sourceforge.net/lists/listinfo/openca-devel

smime.p7s (4K) Download Attachment