Skip to content

Add OCSP responder examples#570

Open
julek-wolfssl wants to merge 2 commits intowolfSSL:masterfrom
julek-wolfssl:ocsp-responder-examples
Open

Add OCSP responder examples#570
julek-wolfssl wants to merge 2 commits intowolfSSL:masterfrom
julek-wolfssl:ocsp-responder-examples

Conversation

@julek-wolfssl
Copy link
Copy Markdown
Member

Three examples demonstrating the new OCSP Responder API:

  1. ocsp-request-response.c - Pure API usage: encode DER OCSP requests
    from certificates, generate signed responses, and verify them
    in memory without networking.

  2. ocsp-responder-http.c - Minimal HTTP server that accepts POST
    requests with DER OCSP payloads and returns signed responses.

  3. nginx-scgi/ - Production-style deployment using nginx as HTTP
    frontend with wolfclu running as an SCGI backend for OCSP
    processing.

Three examples demonstrating the new OCSP Responder API:

1. ocsp-request-response.c - Pure API usage: encode DER OCSP requests
   from certificates, generate signed responses, and verify them
   in memory without networking.

2. ocsp-responder-http.c - Minimal HTTP server that accepts POST
   requests with DER OCSP payloads and returns signed responses.

3. nginx-scgi/ - Production-style deployment using nginx as HTTP
   frontend with wolfclu running as an SCGI backend for OCSP
   processing.
@julek-wolfssl julek-wolfssl self-assigned this Apr 7, 2026
Copilot AI review requested due to automatic review settings April 7, 2026 12:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new ocsp/responder/ set of examples showcasing the wolfSSL OCSP Responder API, including in-memory request/response generation, a minimal HTTP responder, and an nginx+SCGI deployment pattern using wolfCLU.

Changes:

  • Added two C examples: raw DER OCSP request/response and a minimal HTTP POST responder.
  • Added shared PEM->DER file loading helpers and a local Makefile to build the examples.
  • Added nginx+SCGI deployment example (config + run script) and documented how to run all examples.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
ocsp/responder/README.md Documents the new responder examples and how to build/run them.
ocsp/responder/ocsp-request-response.c In-memory OCSP request encode + response sign + verification flow example.
ocsp/responder/ocsp-responder-http.c Minimal socket-based HTTP responder that returns signed OCSP responses.
ocsp/responder/ocsp-load-certs.h Shared file/cert/key loading helpers for the C examples.
ocsp/responder/nginx-scgi/run.sh Script to stand up wolfCLU SCGI backend + nginx frontend for OCSP.
ocsp/responder/nginx-scgi/nginx-ocsp.conf Example nginx config to SCGI-pass OCSP requests to wolfCLU.
ocsp/responder/Makefile Builds the responder examples against an installed wolfSSL.
.gitignore Ignores the newly built responder example binaries.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add missing <time.h> include for time(NULL) usage
- Replace atoi() with strtol() and validate Content-Length in RecvHttp
  and ParsePost to reject negative/overflowing values
- Add SendAll() helper to handle partial send() writes
- Check return values of socket(), setsockopt(), and listen()
}

/* Receive full HTTP request. */
static int RecvHttp(int fd, byte* buf, int bufSz)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCK-2: RecvHttp blocks indefinitely when client sends no Content-Length and keeps connection open

  • File: ocsp/responder/ocsp-responder-http.c:106-134
  • Function: RecvHttp
  • Category: [bug]
  • Confidence: High

Description: When a client sends an HTTP request without a Content-Length header (or sends headers without \r\n\r\n), the recv loop will block indefinitely waiting for more data — the server is single-threaded so this stalls all OCSP processing. There is no read timeout set on the socket. A misbehaving or slow client will hang the entire responder.

While the code is described as "not production-hardened," even for an example/demo server, a single curl or telnet connection that stays open would make the responder completely unresponsive. This is a functional correctness issue for anyone running the example.

Code:

while (total < bufSz - 1) {
    int n = (int)recv(fd, buf + total, (size_t)(bufSz - 1 - total), 0);
    if (n <= 0) break;
    ...
}

Recommendation: Set a SO_RCVTIMEO on the client socket after accept():

Suggested change
static int RecvHttp(int fd, byte* buf, int bufSz)
/* In the while(running) loop, after accept(): */
{
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
}

printf("OCSP responder listening on port %d\n", port);

while (running) {
byte httpBuf[BUF_SZ];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making these static globals? Each are 64KB

{
const byte* p = (const byte*)data;
int remaining = sz;
while (remaining > 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGEST-2: send() returning 0 can cause infinite loop in SendAll

  • File: ocsp/responder/ocsp-responder-http.c:178-180
  • Function: SendAll
  • Category: [bug]
  • Confidence: Medium

Description: send() can return 0 on a non-blocking socket or under certain conditions. The current check if (n < 0) return -1; would cause an infinite loop if send returns 0 repeatedly, since remaining never decreases. While the socket is blocking by default, this is fragile.

Code:

int n = (int)send(fd, p, (size_t)remaining, 0);
if (n < 0) return -1;

Recommendation:

Suggested change
while (remaining > 0) {
if (n <= 0) return -1;

keyFile = argv[3];

wolfSSL_Init();
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGEST-3: Missing SIGPIPE handling in HTTP server

  • File: ocsp/responder/ocsp-responder-http.c:240-247
  • Function: main
  • Category: [bug]
  • Confidence: Medium

Description: When a client disconnects while the server is writing a response, send() will generate SIGPIPE which kills the process by default. The signal handlers set up for SIGINT/SIGTERM do not cover this. This means a client that connects and immediately disconnects can crash the responder.

Recommendation: Add signal(SIGPIPE, SIG_IGN); or set SA_NOSIGPIPE/MSG_NOSIGNAL:

Suggested change
{
signal(SIGPIPE, SIG_IGN);

if (hdrEnd) {
char* cl;
headerEnd = (int)(hdrEnd - (char*)buf) + 4;
cl = strstr((char*)buf, "Content-Length:");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGEST-4: HTTP Content-Length header parsing is case-sensitive with only two variants

  • File: ocsp/responder/ocsp-responder-http.c:121-122,155-156
  • Functions: RecvHttp, ParsePost
  • Category: [convention]
  • Confidence: Low

Description: The code checks for "Content-Length:" and "content-length:" but RFC 7230 specifies HTTP header field names are case-insensitive. Other valid forms like "CONTENT-LENGTH:" or "Content-length:" would be missed. For an example this is probably acceptable, but since wolfSSL users may copy this pattern, a case-insensitive search would be more robust.

Recommendation: Consider a simple case-insensitive strstr helper, or add a brief comment noting this intentional limitation.


printf("\nShutdown.\n");

cleanup:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGEST-5: ocsp-responder-http.c main always returns 0 on error paths

  • File: ocsp/responder/ocsp-responder-http.c:345-352
  • Function: main
  • Category: [bug]
  • Confidence: High

Description: When an error occurs during setup (loading certs, parsing, creating responder, binding socket, etc.), the code jumps to cleanup: which always return 0. This means the process exits with success status even on fatal errors. Compare with ocsp-request-response.c which correctly returns ret.

Code:

cleanup:
    if (sockfd >= 0) close(sockfd);
    if (responder) wc_OcspResponder_free(responder);
    if (caCertInit) wc_FreeDecodedCert(&caCert);
    free(caCertDer);
    free(caKeyDer);
    wolfSSL_Cleanup();
    return 0;  /* Always 0, even on error */

Recommendation: Track error state and return non-zero on failure:

Suggested change
cleanup:
wolfSSL_Cleanup();
return ret;

(and initialize int ret = -1; at declaration, set ret = 0 before the main loop, similar to the pattern in ocsp-request-response.c)


ret = wolfSSL_CertManagerLoadCABuffer(cm, caCertDer, caCertDerSz,
SSL_FILETYPE_ASN1);
if (ret != WOLFSSL_SUCCESS) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT-1: ocsp-request-response.c return code inconsistency on success path

  • File: ocsp/responder/ocsp-request-response.c:310-313
  • Function: main
  • Category: [convention]
  • Confidence: Medium

Description: After wolfSSL_CertManagerLoadCABuffer succeeds, ret holds WOLFSSL_SUCCESS (which is 1). The code then checks ret != WOLFSSL_SUCCESS and continues, but ret remains WOLFSSL_SUCCESS. If wc_NewOCSP fails at line 315, the goto to cleanup returns ret which would be 1 (success) instead of an error. The ret = 0 at line 387 fixes this for the normal path, but error paths between lines 310-320 could return a misleading value.

Recommendation: Reset ret = 0 after the wolfSSL_CertManagerLoadCABuffer success check, or set ret = -1 in the wc_NewOCSP failure block (which the code already does at line 318).


CC = gcc
WOLFSSL_INSTALL_DIR = /usr/local
CFLAGS = -Wall -g -I$(WOLFSSL_INSTALL_DIR)/include
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT-2: Makefile missing -Wextra and -Werror for development

  • File: ocsp/responder/Makefile:9
  • Category: [style]
  • Confidence: Low

Description: The Makefile uses only -Wall for warnings. Adding -Wextra would catch additional issues during development. This is consistent with some other examples in the repo that also only use -Wall, so it follows convention.

Recommendation: No change needed; just noting for awareness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants